ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/Controller.mm
Revision: 1.9
Committed: 2003-04-01T01:56:41Z (21 years, 6 months ago) by nigel
Branch: MAIN
CVS Tags: nigel-build-13
Changes since 1.8: +3 -2 lines
Log Message:
Allow changes in Prefs window while emulator is running

File Contents

# Content
1 /*
2 * Controller.m - Simple application window management.
3 *
4 * $Id: Controller.mm,v 1.8 2003/03/26 00:20:54 nigel Exp $
5 *
6 * Basilisk II (C) 1997-2001 Christian Bauer
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 #import "Controller.h"
24 #import "Emulator.h"
25
26 @implementation Controller
27
28 #import "sysdeps.h" // Types used in Basilisk C++ code
29
30 #import <main.h>
31 #import <prefs.h>
32
33 #define DEBUG 0
34 #import <debug.h>
35
36 #import "misc_macosx.h"
37 #import "video_macosx.h"
38
39 //
40 // Standard NSApplication methods that we override
41 //
42
43 - (id) init
44 {
45 #ifdef ENABLE_MULTIPLE
46 emulators = [NSMutableArray new];
47 #endif
48 return [super init];
49 }
50
51 - (void) dealloc
52 {
53 #ifdef ENABLE_MULTIPLE
54 [emulators dealloc];
55 #endif
56 [super dealloc];
57 }
58
59 - (void) awakeFromNib
60 {
61 #ifdef ENABLE_MULTIPLE
62 [self NewEmulator: self]; // So the user gets something on screen
63 #endif
64 [[NSApplication sharedApplication]
65 setDelegate: self]; // Enable applicationShouldTerminate
66 }
67
68 - (void) sendEvent: (NSEvent *)event;
69 {
70 if ( [self isAnyEmulatorDisplayingSheets] ||
71 [[thePrefsEditor window] isVisible] || ! [self isAnyEmulatorRunning] )
72 [super sendEvent: event];
73 else
74 {
75 NSEventType type = [event type];
76
77 if ( type == NSKeyUp || type == NSKeyDown || type == NSFlagsChanged )
78 [self dispatchKeyEvent: event
79 type: type];
80 else
81 [self dispatchEvent: event
82 type: type];
83 }
84 }
85
86 // NSApplication methods which are invoked through delegation
87
88 - (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication *)app
89 { return YES; }
90
91 - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *)app
92 {
93 short count;
94 char *stillRunningMessage;
95
96 if ( [thePrefsEditor hasEdited] )
97 if ( ChoiceAlert("Preferences have been edited",
98 "Save changes", "Quit") )
99 SavePrefs();
100
101 // if ( edited )
102 // {
103 // NSString *title = [NSString stringWithCString: getString(STR_WARNING_ALERT_TITLE)],
104 // *msg = @"Preferences have been edited",
105 // *def = @"Save changes",
106 // *alt = @"Quit Application",
107 // *other = @"Continue";
108 //
109 // switch ( NSRunAlertPanel(title, msg, def, alt, other, nil) )
110 // {
111 // case NSAlertDefault: savePrefs();
112 // case NSAlertAlternate: return NSTerminateNow;
113 // case NSAlertOther: return NSTerminateCancel;
114 // }
115 // }
116
117
118 if ( [[thePrefsEditor window] isVisible] )
119 [[thePrefsEditor window] performClose: self];
120
121
122 count = [self emulatorCreatedCount];
123
124 if ( count > 0 )
125 {
126 if ( count > 1 )
127 stillRunningMessage = "Emulators are still running\nExiting Basilisk may lose data";
128 else
129 stillRunningMessage = "Emulator is still running\nExiting Basilisk may lose data";
130 if ( ! ChoiceAlert(stillRunningMessage, "Exit", "Continue") )
131 return NSTerminateCancel; // NSTerminateLater?
132 }
133
134 return NSTerminateNow;
135 }
136
137
138 // Event dispatching, called by sendEvent
139
140 - (void) dispatchKeyEvent: (NSEvent *)event
141 type: (NSEventType)type
142 {
143 EmulatorView *view;
144
145 #ifdef ENABLE_MULTIPLE
146 // We need to work out what window's Emulator should receive these messages
147
148
149 int tmp;
150
151 for ( tmp = 0; tmp < [emulators count], ++tmp )
152 {
153 theEmulator = [emulators objectAtIndex: tmp];
154 view = [theEmulator screen];
155
156 if ( [ theEmulator isRunning ] &&
157 ( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) )
158 break;
159 }
160
161 if ( tmp < [emulators count] ) // i.e. if we exited the for loop
162 #else
163 view = [theEmulator screen];
164
165 if ( [theEmulator isRunning] &&
166 ( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) )
167 #endif
168 {
169 D(NSLog(@"Got a key event - %d\n", [event keyCode]));
170 switch ( type )
171 {
172 case NSKeyUp:
173 [view keyUp: event];
174 break;
175 case NSKeyDown:
176 D(NSLog(@"%s - NSKeyDown - %@", __PRETTY_FUNCTION__, event));
177 [view keyDown: event];
178 break;
179 case NSFlagsChanged:
180 [view flagsChanged: event];
181 break;
182 default:
183 NSLog(@"%s - Sent a non-key event (logic error)",
184 __PRETTY_FUNCTION__);
185 [super sendEvent: event];
186 }
187 }
188 else // No Basilisk window is key (maybe a panel or pane).
189 [super sendEvent: event]; // Call NSApplication default
190
191 }
192
193 - (void) dispatchEvent: (NSEvent *)event
194 type: (NSEventType)type
195 {
196 EmulatorView *view;
197 BOOL fullScreen;
198
199 #ifdef ENABLE_MULTIPLE
200 // We need to work out what window's Emulator should receive these messages
201
202
203 int tmp;
204
205 for ( tmp = 0; tmp < [emulators count], ++tmp )
206 {
207 theEmulator = [emulators objectAtIndex: tmp];
208 view = [theEmulator screen];
209 fullScreen = [view isFullScreen];
210
211 if ( [theEmulator isRunning] &&
212 ( fullScreen || [[theEmulator window] isMainWindow] ) )
213 break;
214 }
215
216 if ( tmp < [emulators count] ) // i.e. if we exited the for loop
217 #else
218 view = [theEmulator screen];
219 fullScreen = [view isFullScreen];
220
221 if ( [theEmulator isRunning] &&
222 ( fullScreen || [[theEmulator window] isMainWindow] ) )
223 #endif
224 {
225 if ( fullScreen || [view mouseInView: event] )
226 {
227 switch ( type )
228 {
229 case NSLeftMouseDown:
230 [view mouseDown: event];
231 break;
232 case NSLeftMouseUp:
233 [view mouseUp: event];
234 break;
235 case NSLeftMouseDragged:
236 case NSMouseMoved:
237 if ( fullScreen )
238 [view fullscreenMouseMove];
239 else
240 [view processMouseMove: event];
241 break;
242 default:
243 [super sendEvent: event]; // NSApplication default
244 }
245 return;
246 }
247 }
248
249 // Either the pointer is not in the Emulator's screen, no Basilisk window is running,
250 // or no Basilisk window is main (e.g. there might be a panel or pane up).
251 //
252 // We should just be calling NSApp's default sendEvent, but then for some reason
253 // mouseMoved events are still passed to our EmulatorView, so we filter them out.
254
255 if ( type != NSMouseMoved )
256 [super sendEvent: event];
257 }
258
259
260 // Methods to display documentation:
261
262 - (IBAction) HelpHowTo: (id)sender
263 {
264 NSString *path = [[NSBundle mainBundle] pathForResource: @"HowTo"
265 ofType: @"html"];
266
267 if ( ! path )
268 InfoSheet(@"Cannot find HowTo.html", [theEmulator window]);
269 else
270 if ( ! [[NSWorkspace sharedWorkspace] openFile: path
271 withApplication: @"TextEdit"] )
272 InfoSheet(@"Cannot open HowTo.html with TextEdit", [theEmulator window]);
273 }
274
275 - (IBAction) HelpToDo: (id)sender
276 {
277 NSString *path = [[NSBundle mainBundle] pathForResource: @"ToDo"
278 ofType: @"html"];
279
280 if ( ! path )
281 InfoSheet(@"Cannot find ToDo.html", [theEmulator window]);
282 else
283 if ( ! [[NSWorkspace sharedWorkspace] openFile: path
284 withApplication: @"TextEdit"] )
285 InfoSheet(@"Cannot open ToDo.html with TextEdit", [theEmulator window]);
286 }
287
288 - (IBAction) HelpVersions: (id)sender
289 {
290 NSString *path = [[NSBundle mainBundle] pathForResource: @"Versions"
291 ofType: @"html"];
292
293 if ( ! path )
294 InfoSheet(@"Cannot find Versions.html", [theEmulator window]);
295 else
296 if ( ! [[NSWorkspace sharedWorkspace] openFile: path
297 withApplication: @"TextEdit"] )
298 InfoSheet(@"Cannot open Versions.html with TextEdit",
299 [theEmulator window]);
300 }
301
302
303 // Menu items which for managing more than one window
304
305 #ifdef ENABLE_MULTIPLE
306
307 - (IBAction) NewEmulator: (id)sender
308 {
309 NSString *title;
310
311 if ( ! [NSBundle loadNibNamed:@"Win512x342" owner:self] )
312 {
313 NSLog(@"%s - LoadNibNamed@Win512x342 failed", __PRETTY_FUNCTION__);
314 return;
315 }
316
317 if ( theEmulator == nil)
318 {
319 NSLog(@"%s - Newly created emulator's NIB stuff not fully linked?", __PRETTY_FUNCTION__);
320 return;
321 }
322
323 [emulators addObject: theEmulator];
324 title = [NSString localizedStringWithFormat:@"BasiliskII Emulator %d", [emulators count]];
325 [theEmulator -> win setTitle: title];
326 }
327
328 - (IBAction) PauseAll: (id)sender
329 {
330 [emulators makeObjectsPerformSelector:@selector(Suspend:)
331 withObject:self];
332 }
333
334 - (IBAction) RunAll: (id)sender
335 {
336 [emulators makeObjectsPerformSelector:@selector(Resume:)
337 withObject:self];
338 }
339
340 - (IBAction) TerminateAll: (id)sender
341 {
342 [emulators makeObjectsPerformSelector:@selector(Terminate:)
343 withObject:self];
344 }
345
346 #endif
347
348 - (BOOL) isAnyEmulatorDisplayingSheets
349 {
350 #ifdef ENABLE_MULTIPLE
351 int tmp;
352
353 for ( tmp = 0; tmp < [emulators count], ++tmp )
354 if ( [[[emulators objectAtIndex: tmp] window] attachedSheet] )
355 break;
356
357 if ( tmp < [emulators count] ) // i.e. if we exited the for loop
358 #else
359 if ( [[theEmulator window] attachedSheet] )
360 #endif
361 return TRUE;
362
363 return FALSE;
364 }
365
366 - (BOOL) isAnyEmulatorRunning
367 {
368 #ifdef ENABLE_MULTIPLE
369 int tmp;
370
371 for ( tmp = 0; tmp < [emulators count], ++tmp )
372 if ( [[emulators objectAtIndex: tmp] isRunning] )
373 break;
374
375 if ( tmp < [emulators count] ) // i.e. if we exited the for loop
376 #else
377 if ( [theEmulator isRunning] )
378 #endif
379 return TRUE;
380
381 return FALSE;
382 }
383
384 - (short) emulatorCreatedCount
385 {
386 short count = 0;
387 #ifdef ENABLE_MULTIPLE
388 int tmp;
389
390 for ( tmp = 0; tmp < [emulators count], ++tmp )
391 if ( [[emulators objectAtIndex: tmp] uaeCreated] )
392 ++count;
393 #else
394 if ( [theEmulator uaeCreated] )
395 ++count;
396 #endif
397
398 return count;
399 }
400
401 @end