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, 2 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

# User Rev Content
1 nigel 1.2 /*
2     * Controller.m - Simple application window management.
3     *
4 nigel 1.9 * $Id: Controller.mm,v 1.8 2003/03/26 00:20:54 nigel Exp $
5 nigel 1.2 *
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 nigel 1.6 #import "misc_macosx.h"
37 nigel 1.2 #import "video_macosx.h"
38    
39     //
40     // Standard NSApplication methods that we override
41     //
42    
43     - (id) init
44     {
45     #ifdef ENABLE_MULTIPLE
46 nigel 1.5 emulators = [NSMutableArray new];
47 nigel 1.2 #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 nigel 1.9 if ( [self isAnyEmulatorDisplayingSheets] ||
71     [[thePrefsEditor window] isVisible] || ! [self isAnyEmulatorRunning] )
72 nigel 1.4 [super sendEvent: event];
73     else
74     {
75     NSEventType type = [event type];
76 nigel 1.2
77 nigel 1.4 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 nigel 1.2 }
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 nigel 1.4 view = [theEmulator screen];
155    
156     if ( [ theEmulator isRunning ] &&
157     ( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) )
158 nigel 1.2 break;
159     }
160    
161     if ( tmp < [emulators count] ) // i.e. if we exited the for loop
162     #else
163 nigel 1.4 view = [theEmulator screen];
164    
165     if ( [theEmulator isRunning] &&
166     ( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) )
167 nigel 1.2 #endif
168     {
169 nigel 1.4 D(NSLog(@"Got a key event - %d\n", [event keyCode]));
170 nigel 1.2 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 nigel 1.4 EmulatorView *view;
197 nigel 1.7 BOOL fullScreen;
198 nigel 1.4
199 nigel 1.2 #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 nigel 1.4 view = [theEmulator screen];
209 nigel 1.7 fullScreen = [view isFullScreen];
210 nigel 1.4
211     if ( [theEmulator isRunning] &&
212 nigel 1.7 ( fullScreen || [[theEmulator window] isMainWindow] ) )
213 nigel 1.2 break;
214     }
215    
216     if ( tmp < [emulators count] ) // i.e. if we exited the for loop
217     #else
218 nigel 1.4 view = [theEmulator screen];
219 nigel 1.7 fullScreen = [view isFullScreen];
220 nigel 1.4
221     if ( [theEmulator isRunning] &&
222 nigel 1.7 ( fullScreen || [[theEmulator window] isMainWindow] ) )
223 nigel 1.2 #endif
224     {
225 nigel 1.7 if ( fullScreen || [view mouseInView: event] )
226 nigel 1.2 {
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 nigel 1.7 if ( fullScreen )
238     [view fullscreenMouseMove];
239     else
240     [view processMouseMove: event];
241 nigel 1.2 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 nigel 1.6
259    
260     // Methods to display documentation:
261    
262 nigel 1.8 - (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 nigel 1.6 - (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 nigel 1.8 InfoSheet(@"Cannot open Versions.html with TextEdit",
299     [theEmulator window]);
300 nigel 1.6 }
301    
302    
303     // Menu items which for managing more than one window
304 nigel 1.2
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 nigel 1.4
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 nigel 1.2
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