d5f74e42 |
1 | // Copyright (c) 2013-2014 OPEN CASCADE SAS |
4fe56619 |
2 | // |
973c2be1 |
3 | // This file is part of Open CASCADE Technology software library. |
4fe56619 |
4 | // |
d5f74e42 |
5 | // This library is free software; you can redistribute it and/or modify it under |
6 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
7 | // by the Free Software Foundation, with special exception defined in the file |
8 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
9 | // distribution for complete text of the license and disclaimer of any warranty. |
4fe56619 |
10 | // |
973c2be1 |
11 | // Alternatively, this file may be used under the terms of Open CASCADE |
12 | // commercial license or contractual agreement. |
4fe56619 |
13 | |
14 | #if defined(__APPLE__) && !defined(MACOSX_USE_GLX) |
15 | |
16 | #import <Cocoa/Cocoa.h> |
17 | |
18 | #include <Cocoa_Window.hxx> |
19 | #include <ViewerTest.hxx> |
20 | #include <V3d_View.hxx> |
21 | #include <V3d_Viewer.hxx> |
22 | #include <AIS_InteractiveContext.hxx> |
23 | #include <NIS_View.hxx> |
18d715bd |
24 | #include <TCollection_AsciiString.hxx> |
25 | #include <NCollection_DoubleMap.hxx> |
4fe56619 |
26 | |
27 | //! Custom Cocoa view to handle events |
28 | @interface ViewerTest_CocoaEventManagerView : NSView |
29 | @end |
30 | |
18d715bd |
31 | //! Custom Cocoa window delegate to handle window events |
32 | @interface Cocoa_WindowController : NSObject <NSWindowDelegate> |
33 | @end |
34 | |
35 | extern void ActivateView (const TCollection_AsciiString& theViewName); |
4fe56619 |
36 | extern void VT_ProcessExpose(); |
37 | extern void VT_ProcessConfigure(); |
38 | extern void VT_ProcessKeyPress (const char* theBuffer); |
39 | extern void VT_ProcessMotion(); |
40 | extern void VT_ProcessButton3Press(); |
41 | extern void VT_ProcessButton3Release(); |
42 | extern void VT_ProcessControlButton2Motion(); |
43 | extern void VT_ProcessControlButton3Motion(); |
44 | extern Standard_Boolean VT_ProcessButton1Press (Standard_Integer theArgsNb, |
45 | const char** theArgsVec, |
46 | Standard_Boolean theToPick, |
47 | Standard_Boolean theIsShift); |
48 | extern void VT_ProcessButton1Release(Standard_Boolean theIsShift); |
49 | |
18d715bd |
50 | extern NCollection_DoubleMap <TCollection_AsciiString, Handle(V3d_View)> ViewerTest_myViews; |
4fe56619 |
51 | extern int X_Motion; // Current cursor position |
52 | extern int Y_Motion; |
53 | extern int X_ButtonPress; // Last ButtonPress position |
54 | extern int Y_ButtonPress; |
55 | extern Standard_Boolean IsDragged; |
56 | |
18d715bd |
57 | // ======================================================================= |
58 | // function : SetCocoaWindowTitle |
59 | // purpose : |
60 | // ======================================================================= |
61 | void SetCocoaWindowTitle (const Handle(Cocoa_Window)& theWindow, Standard_CString theTitle) |
62 | { |
63 | NSView* aView = theWindow->HView(); |
64 | NSWindow* aWindow = [aView window]; |
65 | |
66 | NSString* aTitleNS = [[NSString alloc] initWithUTF8String: theTitle]; |
67 | [aWindow setTitle: aTitleNS]; |
68 | [aTitleNS release]; |
69 | |
70 | } |
71 | |
72 | // ======================================================================= |
73 | // function : GetCocoaScreenResolution |
74 | // purpose : |
75 | // ======================================================================= |
76 | void GetCocoaScreenResolution (Standard_Integer& theWidth, Standard_Integer& theHeight) |
77 | { |
78 | NSRect aRect = [[NSScreen mainScreen] visibleFrame]; |
79 | theWidth = (Standard_Integer )aRect.size.width; |
80 | theHeight = (Standard_Integer )aRect.size.height; |
81 | } |
82 | |
83 | // ======================================================================= |
84 | // function : FindViewId |
85 | // purpose : |
86 | // ======================================================================= |
87 | TCollection_AsciiString FindViewId (const NSWindow* theWindow) |
88 | { |
89 | TCollection_AsciiString aViewId = ""; |
90 | NCollection_DoubleMap<TCollection_AsciiString, Handle(V3d_View)>::Iterator anIter(ViewerTest_myViews); |
91 | for (;anIter.More();anIter.Next()) |
92 | { |
93 | NSView* aView = Handle(Cocoa_Window)::DownCast |
94 | (anIter.Value()->Window())->HView(); |
95 | NSWindow* aWindow = [aView window]; |
96 | if (aWindow == theWindow) |
97 | { |
98 | aViewId = anIter.Key1(); |
99 | return aViewId; |
100 | } |
101 | } |
102 | return aViewId; |
103 | } |
104 | |
105 | @implementation Cocoa_WindowController |
106 | |
107 | - (void )windowWillClose: (NSNotification* )theNotification |
108 | { |
109 | TCollection_AsciiString aViewId = ""; |
110 | if (ViewerTest_myViews.IsBound2 (ViewerTest::CurrentView())) |
111 | { |
112 | aViewId = ViewerTest_myViews.Find2 (ViewerTest::CurrentView()); |
113 | } |
114 | ViewerTest::RemoveView (aViewId); |
115 | } |
116 | |
117 | - (void )windowDidBecomeKey: (NSNotification* )theNotification |
118 | { |
119 | NSWindow *aWindow = [theNotification object]; |
120 | ActivateView (FindViewId (aWindow)); |
121 | } |
122 | |
123 | @end |
124 | |
4fe56619 |
125 | // ======================================================================= |
126 | // function : ViewerMainLoop |
127 | // purpose : |
128 | // ======================================================================= |
129 | int ViewerMainLoop (Standard_Integer, const char** ) |
130 | { |
131 | // unused |
132 | return 0; |
133 | } |
134 | |
135 | // ======================================================================= |
136 | // function : ViewerTest_SetCocoaEventManagerView |
137 | // purpose : |
138 | // ======================================================================= |
139 | void ViewerTest_SetCocoaEventManagerView (const Handle(Cocoa_Window)& theWindow) |
140 | { |
141 | if (theWindow.IsNull()) |
142 | { |
143 | return; |
144 | } |
145 | |
146 | NSWindow* aWin = [theWindow->HView() window]; |
147 | NSRect aBounds = [[aWin contentView] bounds]; |
148 | |
149 | ViewerTest_CocoaEventManagerView* aView = [[ViewerTest_CocoaEventManagerView alloc] initWithFrame: aBounds]; |
150 | |
151 | // replace content view in the window |
152 | theWindow->SetHView (aView); |
153 | |
18d715bd |
154 | // set delegate for window |
155 | Cocoa_WindowController* aWindowController = [[[Cocoa_WindowController alloc] init] autorelease]; |
156 | [aWin setDelegate: aWindowController]; |
157 | |
4fe56619 |
158 | // make view as first responder in winow to capture all useful events |
159 | [aWin makeFirstResponder: aView]; |
160 | [aWin setAcceptsMouseMovedEvents: YES]; |
161 | |
162 | // should be retained by parent NSWindow |
163 | [aView release]; |
164 | } |
165 | |
166 | // ======================================================================= |
167 | // function : getMouseCoords |
168 | // purpose : Retrieve cursor position |
169 | // ======================================================================= |
170 | static void getMouseCoords (NSView* theView, |
171 | NSEvent* theEvent, |
172 | Standard_Integer& theX, |
173 | Standard_Integer& theY) |
174 | { |
175 | NSPoint aMouseLoc = [theView convertPoint: [theEvent locationInWindow] fromView: nil]; |
176 | NSRect aBounds = [theView bounds]; |
177 | |
178 | theX = Standard_Integer(aMouseLoc.x); |
179 | theY = Standard_Integer(aBounds.size.height - aMouseLoc.y); |
180 | } |
181 | |
182 | @implementation ViewerTest_CocoaEventManagerView |
183 | |
184 | // ======================================================================= |
185 | // function : setFrameSize |
186 | // purpose : |
187 | // ======================================================================= |
188 | - (void )setFrameSize: (NSSize )theNewSize |
189 | { |
190 | [super setFrameSize: theNewSize]; |
191 | VT_ProcessConfigure(); |
192 | } |
193 | |
194 | // ======================================================================= |
195 | // function : drawRect |
196 | // purpose : |
197 | // ======================================================================= |
198 | - (void )drawRect: (NSRect )theDirtyRect |
199 | { |
200 | VT_ProcessExpose(); |
201 | } |
202 | |
203 | // ======================================================================= |
204 | // function : mouseMoved |
205 | // purpose : |
206 | // ======================================================================= |
207 | - (void )mouseMoved: (NSEvent* )theEvent |
208 | { |
209 | getMouseCoords (self, theEvent, X_Motion, Y_Motion); |
210 | VT_ProcessMotion(); |
211 | } |
212 | |
213 | // ======================================================================= |
214 | // function : acceptsFirstResponder |
215 | // purpose : |
216 | // ======================================================================= |
217 | - (BOOL )acceptsFirstResponder |
218 | { |
219 | return YES; |
220 | } |
221 | |
222 | // ======================================================================= |
223 | // function : mouseDown |
224 | // purpose : |
225 | // ======================================================================= |
226 | - (void )mouseDown: (NSEvent* )theEvent |
227 | { |
228 | getMouseCoords (self, theEvent, X_ButtonPress, Y_ButtonPress); |
229 | VT_ProcessButton1Press (0, NULL, Standard_False, [theEvent modifierFlags] & NSShiftKeyMask); |
230 | } |
231 | |
232 | // ======================================================================= |
233 | // function : mouseUp |
234 | // purpose : |
235 | // ======================================================================= |
236 | - (void )mouseUp: (NSEvent* )theEvent |
237 | { |
238 | getMouseCoords (self, theEvent, X_Motion, Y_Motion); |
239 | VT_ProcessButton1Release([theEvent modifierFlags] & NSShiftKeyMask); |
240 | } |
241 | |
242 | |
243 | // ======================================================================= |
244 | // function : mouseDragged |
245 | // purpose : |
246 | // ======================================================================= |
247 | - (void )mouseDragged: (NSEvent* )theEvent |
248 | { |
249 | IsDragged = Standard_True; |
250 | if ([theEvent modifierFlags] & NSControlKeyMask) |
251 | { |
252 | getMouseCoords (self, theEvent, X_Motion, Y_Motion); |
253 | VT_ProcessControlButton2Motion(); |
254 | } |
255 | } |
256 | |
257 | // ======================================================================= |
258 | // function : rightMouseDown |
259 | // purpose : |
260 | // ======================================================================= |
261 | - (void )rightMouseDown: (NSEvent* )theEvent |
262 | { |
263 | getMouseCoords (self, theEvent, X_ButtonPress, Y_ButtonPress); |
264 | VT_ProcessButton3Press(); // Start rotation |
265 | } |
266 | |
267 | // ======================================================================= |
268 | // function : rightMouseUp |
269 | // purpose : |
270 | // ======================================================================= |
271 | - (void )rightMouseUp: (NSEvent* )theEvent |
272 | { |
273 | VT_ProcessButton3Release(); |
274 | } |
275 | |
276 | // ======================================================================= |
277 | // function : rightMouseDragged |
278 | // purpose : |
279 | // ======================================================================= |
280 | - (void )rightMouseDragged: (NSEvent* )theEvent |
281 | { |
282 | if ([theEvent modifierFlags] & NSControlKeyMask) |
283 | { |
284 | getMouseCoords (self, theEvent, X_Motion, Y_Motion); |
285 | VT_ProcessControlButton3Motion(); |
286 | } |
287 | } |
288 | |
289 | // ======================================================================= |
290 | // function : scrollWheel |
291 | // purpose : |
292 | // ======================================================================= |
293 | - (void )scrollWheel: (NSEvent* )theEvent |
294 | { |
295 | float aDelta = [theEvent deltaY]; |
296 | if (Abs (aDelta) < 0.001) |
297 | { |
298 | // a lot of values near zero can be generated by touchpad |
299 | return; |
300 | } |
301 | |
302 | ViewerTest::CurrentView()->Zoom (0, 0, aDelta, aDelta); |
303 | } |
304 | |
305 | // ======================================================================= |
306 | // function : keyDown |
307 | // purpose : |
308 | // ======================================================================= |
309 | - (void )keyDown: (NSEvent* )theEvent |
310 | { |
311 | NSString* aStringNs = [theEvent characters]; |
312 | if (aStringNs == NULL || [aStringNs length] == 0) |
313 | { |
314 | return; |
315 | } |
316 | |
317 | const Standard_CString aString = [aStringNs UTF8String]; |
318 | VT_ProcessKeyPress (aString); |
319 | } |
320 | |
321 | @end |
322 | |
323 | #endif |