ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/BasiliskII/src/MacOSX/Controller.mm
Revision: 1.15
Committed: 2008-01-01T09:40:32Z (16 years, 5 months ago) by gbeauche
Branch: MAIN
CVS Tags: HEAD
Changes since 1.14: +2 -2 lines
Log Message:
Happy New Year!

File Contents

# User Rev Content
1 nigel 1.2 /*
2     * Controller.m - Simple application window management.
3     *
4 gbeauche 1.15 * $Id: Controller.mm,v 1.14 2006/03/10 08:16:56 nigel Exp $
5 nigel 1.2 *
6 gbeauche 1.15 * Basilisk II (C) 1997-2008 Christian Bauer
7 nigel 1.2 *
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     #import "sysdeps.h" // Types used in Basilisk C++ code
27    
28     #import <main.h>
29     #import <prefs.h>
30    
31     #define DEBUG 0
32     #import <debug.h>
33    
34 nigel 1.6 #import "misc_macosx.h"
35 nigel 1.2 #import "video_macosx.h"
36    
37 nigel 1.13 @implementation Controller
38    
39 nigel 1.2 //
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.14 // We can either process the event ourselves,
71     // or pass it to our superclass for the other UI objects to process
72     bool passToSuper = false;
73    
74 nigel 1.9 if ( [self isAnyEmulatorDisplayingSheets] ||
75     [[thePrefsEditor window] isVisible] || ! [self isAnyEmulatorRunning] )
76 nigel 1.14 passToSuper = true;
77    
78     if ( [[theEmulator screen] isFullScreen] )
79     passToSuper = false;
80    
81     if ( passToSuper )
82     [super sendEvent: event]; // NSApplication default
83 nigel 1.4 else
84     {
85     NSEventType type = [event type];
86 nigel 1.2
87 nigel 1.4 if ( type == NSKeyUp || type == NSKeyDown || type == NSFlagsChanged )
88     [self dispatchKeyEvent: event
89     type: type];
90     else
91     [self dispatchEvent: event
92     type: type];
93     }
94 nigel 1.2 }
95    
96     // NSApplication methods which are invoked through delegation
97    
98     - (BOOL) applicationShouldTerminateAfterLastWindowClosed: (NSApplication *)app
99     { return YES; }
100    
101     - (NSApplicationTerminateReply) applicationShouldTerminate: (NSApplication *)app
102     {
103     short count;
104     char *stillRunningMessage;
105    
106     if ( [thePrefsEditor hasEdited] )
107     if ( ChoiceAlert("Preferences have been edited",
108     "Save changes", "Quit") )
109     SavePrefs();
110    
111     // if ( edited )
112     // {
113     // NSString *title = [NSString stringWithCString: getString(STR_WARNING_ALERT_TITLE)],
114     // *msg = @"Preferences have been edited",
115     // *def = @"Save changes",
116     // *alt = @"Quit Application",
117     // *other = @"Continue";
118     //
119     // switch ( NSRunAlertPanel(title, msg, def, alt, other, nil) )
120     // {
121 nigel 1.10 // case NSAlertDefault: savePrefs();
122     // case NSAlertAlternate: return NSTerminateNow;
123     // case NSAlertOther: return NSTerminateCancel;
124 nigel 1.2 // }
125     // }
126    
127    
128     if ( [[thePrefsEditor window] isVisible] )
129     [[thePrefsEditor window] performClose: self];
130    
131    
132     count = [self emulatorCreatedCount];
133    
134     if ( count > 0 )
135     {
136     if ( count > 1 )
137     stillRunningMessage = "Emulators are still running\nExiting Basilisk may lose data";
138     else
139     stillRunningMessage = "Emulator is still running\nExiting Basilisk may lose data";
140     if ( ! ChoiceAlert(stillRunningMessage, "Exit", "Continue") )
141     return NSTerminateCancel; // NSTerminateLater?
142     }
143    
144     return NSTerminateNow;
145     }
146    
147    
148     // Event dispatching, called by sendEvent
149    
150     - (void) dispatchKeyEvent: (NSEvent *)event
151     type: (NSEventType)type
152     {
153     EmulatorView *view;
154    
155     #ifdef ENABLE_MULTIPLE
156     // We need to work out what window's Emulator should receive these messages
157    
158    
159     int tmp;
160    
161     for ( tmp = 0; tmp < [emulators count], ++tmp )
162     {
163     theEmulator = [emulators objectAtIndex: tmp];
164 nigel 1.4 view = [theEmulator screen];
165    
166     if ( [ theEmulator isRunning ] &&
167     ( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) )
168 nigel 1.2 break;
169     }
170    
171     if ( tmp < [emulators count] ) // i.e. if we exited the for loop
172     #else
173 nigel 1.4 view = [theEmulator screen];
174    
175     if ( [theEmulator isRunning] &&
176     ( [[theEmulator window] isKeyWindow] || [view isFullScreen] ) )
177 nigel 1.2 #endif
178     {
179 nigel 1.4 D(NSLog(@"Got a key event - %d\n", [event keyCode]));
180 nigel 1.2 switch ( type )
181     {
182     case NSKeyUp:
183     [view keyUp: event];
184     break;
185     case NSKeyDown:
186     D(NSLog(@"%s - NSKeyDown - %@", __PRETTY_FUNCTION__, event));
187     [view keyDown: event];
188     break;
189     case NSFlagsChanged:
190     [view flagsChanged: event];
191     break;
192     default:
193     NSLog(@"%s - Sent a non-key event (logic error)",
194     __PRETTY_FUNCTION__);
195     [super sendEvent: event];
196     }
197     }
198     else // No Basilisk window is key (maybe a panel or pane).
199     [super sendEvent: event]; // Call NSApplication default
200    
201     }
202    
203     - (void) dispatchEvent: (NSEvent *)event
204     type: (NSEventType)type
205     {
206 nigel 1.4 EmulatorView *view;
207 nigel 1.7 BOOL fullScreen;
208 nigel 1.4
209 nigel 1.2 #ifdef ENABLE_MULTIPLE
210     // We need to work out what window's Emulator should receive these messages
211    
212    
213     int tmp;
214    
215     for ( tmp = 0; tmp < [emulators count], ++tmp )
216     {
217     theEmulator = [emulators objectAtIndex: tmp];
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 break;
224     }
225    
226     if ( tmp < [emulators count] ) // i.e. if we exited the for loop
227     #else
228 nigel 1.4 view = [theEmulator screen];
229 nigel 1.7 fullScreen = [view isFullScreen];
230 nigel 1.4
231     if ( [theEmulator isRunning] &&
232 nigel 1.7 ( fullScreen || [[theEmulator window] isMainWindow] ) )
233 nigel 1.2 #endif
234     {
235 nigel 1.7 if ( fullScreen || [view mouseInView: event] )
236 nigel 1.2 {
237     switch ( type )
238     {
239     case NSLeftMouseDown:
240     [view mouseDown: event];
241     break;
242     case NSLeftMouseUp:
243     [view mouseUp: event];
244     break;
245     case NSLeftMouseDragged:
246     case NSMouseMoved:
247 nigel 1.7 if ( fullScreen )
248     [view fullscreenMouseMove];
249     else
250     [view processMouseMove: event];
251 nigel 1.2 break;
252     default:
253     [super sendEvent: event]; // NSApplication default
254     }
255     return;
256     }
257     }
258    
259     // Either the pointer is not in the Emulator's screen, no Basilisk window is running,
260     // or no Basilisk window is main (e.g. there might be a panel or pane up).
261     //
262     // We should just be calling NSApp's default sendEvent, but then for some reason
263     // mouseMoved events are still passed to our EmulatorView, so we filter them out.
264    
265     if ( type != NSMouseMoved )
266     [super sendEvent: event];
267     }
268 nigel 1.6
269    
270     // Methods to display documentation:
271    
272 nigel 1.8 - (IBAction) HelpHowTo: (id)sender
273     {
274 nigel 1.10 NSString *path = [[NSBundle mainBundle] pathForResource: @"HowTo"
275     ofType: @"html"];
276 nigel 1.8
277 nigel 1.10 if ( ! path )
278     InfoSheet(@"Cannot find HowTo.html", [theEmulator window]);
279     else
280     if ( ! [[NSWorkspace sharedWorkspace] openFile: path] )
281     InfoSheet(@"Cannot open HowTo.html with default app", [theEmulator window]);
282 nigel 1.8 }
283    
284 nigel 1.6 - (IBAction) HelpToDo: (id)sender
285     {
286 nigel 1.10 NSString *path = [[NSBundle mainBundle] pathForResource: @"ToDo"
287     ofType: @"html"];
288 nigel 1.6
289 nigel 1.10 if ( ! path )
290     InfoSheet(@"Cannot find ToDo.html", [theEmulator window]);
291     else
292     if ( ! [[NSWorkspace sharedWorkspace] openFile: path
293     withApplication: @"TextEdit"] )
294     InfoSheet(@"Cannot open ToDo.html with TextEdit", [theEmulator window]);
295 nigel 1.6 }
296    
297     - (IBAction) HelpVersions: (id)sender
298     {
299 nigel 1.10 NSString *path = [[NSBundle mainBundle] pathForResource: @"Versions"
300     ofType: @"html"];
301 nigel 1.6
302 nigel 1.10 if ( ! path )
303     InfoSheet(@"Cannot find Versions.html", [theEmulator window]);
304     else
305     if ( ! [[NSWorkspace sharedWorkspace] openFile: path
306     withApplication: @"TextEdit"] )
307     InfoSheet(@"Cannot open Versions.html with TextEdit",
308 nigel 1.8 [theEmulator window]);
309 nigel 1.6 }
310    
311    
312     // Menu items which for managing more than one window
313 nigel 1.2
314     #ifdef ENABLE_MULTIPLE
315    
316     - (IBAction) NewEmulator: (id)sender
317     {
318     NSString *title;
319    
320     if ( ! [NSBundle loadNibNamed:@"Win512x342" owner:self] )
321     {
322     NSLog(@"%s - LoadNibNamed@Win512x342 failed", __PRETTY_FUNCTION__);
323     return;
324     }
325    
326     if ( theEmulator == nil)
327     {
328     NSLog(@"%s - Newly created emulator's NIB stuff not fully linked?", __PRETTY_FUNCTION__);
329     return;
330     }
331    
332     [emulators addObject: theEmulator];
333     title = [NSString localizedStringWithFormat:@"BasiliskII Emulator %d", [emulators count]];
334     [theEmulator -> win setTitle: title];
335     }
336    
337     - (IBAction) PauseAll: (id)sender
338     {
339     [emulators makeObjectsPerformSelector:@selector(Suspend:)
340     withObject:self];
341     }
342    
343     - (IBAction) RunAll: (id)sender
344     {
345     [emulators makeObjectsPerformSelector:@selector(Resume:)
346     withObject:self];
347     }
348    
349     - (IBAction) TerminateAll: (id)sender
350     {
351     [emulators makeObjectsPerformSelector:@selector(Terminate:)
352     withObject:self];
353     }
354    
355     #endif
356 nigel 1.4
357     - (BOOL) isAnyEmulatorDisplayingSheets
358     {
359     #ifdef ENABLE_MULTIPLE
360     int tmp;
361    
362     for ( tmp = 0; tmp < [emulators count], ++tmp )
363     if ( [[[emulators objectAtIndex: tmp] window] attachedSheet] )
364     break;
365    
366     if ( tmp < [emulators count] ) // i.e. if we exited the for loop
367     #else
368     if ( [[theEmulator window] attachedSheet] )
369     #endif
370     return TRUE;
371    
372     return FALSE;
373     }
374 nigel 1.2
375     - (BOOL) isAnyEmulatorRunning
376     {
377     #ifdef ENABLE_MULTIPLE
378     int tmp;
379    
380     for ( tmp = 0; tmp < [emulators count], ++tmp )
381     if ( [[emulators objectAtIndex: tmp] isRunning] )
382     break;
383    
384     if ( tmp < [emulators count] ) // i.e. if we exited the for loop
385     #else
386     if ( [theEmulator isRunning] )
387     #endif
388     return TRUE;
389    
390     return FALSE;
391     }
392    
393     - (short) emulatorCreatedCount
394     {
395     short count = 0;
396     #ifdef ENABLE_MULTIPLE
397     int tmp;
398    
399     for ( tmp = 0; tmp < [emulators count], ++tmp )
400     if ( [[emulators objectAtIndex: tmp] uaeCreated] )
401     ++count;
402     #else
403     if ( [theEmulator uaeCreated] )
404     ++count;
405     #endif
406    
407     return count;
408     }
409    
410 nigel 1.10 @end