source: trunk/Cocoa/F-Script Anywhere/Source/FSAController.m @ 454

Last change on this file since 454 was 454, checked in by Nicholas Riley, 12 years ago

More nib cleanup; stop Escape from closing the workspace (still need Option for completion, though.)

File size: 9.2 KB
Line 
1//
2//  FSAController.m
3//  F-Script Anywhere
4//
5//  Created by Nicholas Riley on Fri Feb 01 2002.
6//  Copyright (c) 2002 Nicholas Riley. All rights reserved.
7//
8
9/*
10
11 F-Script Anywhere is free software; you can redistribute it and/or modify
12 it under the terms of the GNU General Public License as published by
13 the Free Software Foundation; either version 2 of the License, or
14 (at your option) any later version.
15
16 F-Script Anywhere is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with F-Script Anywhere; if not, write to the Free Software
23 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24
25*/
26
27#import "FSAController.h"
28#import "FSAViewAssociationController.h"
29#import "FSAnywhere.h"
30#import "FSAWindowManager.h"
31#import <FScript/FSInterpreter.h>
32
33@class ShellView;
34
35// XXX workaround for lack of focus on FSInterpreterView
36@interface CLIView : NSView
37- (ShellView *)shellView;
38@end
39
40@interface FSInterpreterView (FSAWorkaround)
41- (CLIView *)cliView;
42@end
43
44@interface NSWindow (RoundedCorners)
45- (void)setBottomCornerRounded:(BOOL)yn;
46@end
47
48@implementation FSAController
49
50// derived from TETextWatcher.m in Mike Ferris's TextExtras
51+ (void)installMenu;
52{
53    static BOOL alreadyInstalled = NO;
54    NSMenu *mainMenu = nil;
55   
56    if (!alreadyInstalled && ((mainMenu = [NSApp mainMenu]) != nil)) {
57        NSMenu *insertIntoMenu = nil;
58        NSMenuItem *item;
59        unsigned insertLoc = NSNotFound;
60        NSBundle *bundle = [NSBundle bundleForClass: self];
61        NSMenu * beforeSubmenu = [NSApp windowsMenu];
62        // Succeed or fail, we do not try again.
63        alreadyInstalled = YES;
64
65        // Add it to the main menu.  We try to put it right before the Windows menu if there is one, or right before the Services menu if there is one, and if there's neither we put it right before the the last submenu item (ie above Quit and Hide on Mach, at the end on Windows.)
66
67        if (!beforeSubmenu) {
68            beforeSubmenu = [NSApp servicesMenu];
69        }
70
71        insertIntoMenu = mainMenu;
72
73        if (beforeSubmenu) {
74            NSArray *itemArray = [insertIntoMenu itemArray];
75            unsigned i, c = [itemArray count];
76
77            // Default to end of menu
78            insertLoc = c;
79
80            for (i=0; i<c; i++) {
81                if ([[itemArray objectAtIndex:i] target] == beforeSubmenu) {
82                    insertLoc = i;
83                    break;
84                }
85            }
86        } else {
87            NSArray *itemArray = [insertIntoMenu itemArray];
88            unsigned i = [itemArray count];
89
90            // Default to end of menu
91            insertLoc = i;
92
93            while (i-- > 0) {
94                if ([[itemArray objectAtIndex:i] hasSubmenu]) {
95                    insertLoc = i+1;
96                    break;
97                }
98            }
99        }
100        if (insertIntoMenu) {
101            NSMenu *fsaMenu = [[NSMenu allocWithZone: [NSMenu menuZone]] initWithTitle:NSLocalizedStringFromTableInBundle(@"FSA", @"FSA", bundle, @"Title of F-Script Anywhere menu")];
102
103            item = [insertIntoMenu insertItemWithTitle: NSLocalizedStringFromTableInBundle(@"FSA", @"FSA", bundle, @"Title of F-Script Anywhere menu") action:NULL keyEquivalent:@"" atIndex:insertLoc];
104            [insertIntoMenu setSubmenu:fsaMenu forItem:item];
105            [fsaMenu release];
106
107            // Add the items for the commands.
108            item = [fsaMenu addItemWithTitle: NSLocalizedStringFromTableInBundle(@"New F-Script Workspace", @"FSA", bundle, @"Title of F-Script Workspace menu item") action:@selector(createInterpreterWindow:) keyEquivalent: @""];
109            [item setTarget: self];
110            item = [fsaMenu addItemWithTitle: NSLocalizedStringFromTableInBundle(@"Browser for Target...", @"FSA", bundle, @"Title of F-Script Workspace menu item") action:@selector(createBrowserForSelection:) keyEquivalent: @""];
111            [item setTarget: self];
112            [fsaMenu addItem: [NSMenuItem separatorItem]];
113            item = [fsaMenu addItemWithTitle: NSLocalizedStringFromTableInBundle(@"About F-Script Anywhere", @"FSA", bundle, @"Title of Info Panel menu item") action:@selector(showInfo:) keyEquivalent: @""];
114            [item setTarget: self];
115            [[FSAWindowManager sharedManager] setWindowMenu: fsaMenu];
116        }
117    }
118   
119    // Open up a workspace if the user wants one
120    if ([[[[NSUserDefaults standardUserDefaults] persistentDomainForName: @"net.sabi.FScriptAnywhereApp"] objectForKey:@"OpenWorkspaceOnInstall"] boolValue]) {
121        [FSAController createInterpreterWindow: nil];
122    }
123}
124
125+ (BOOL)validateMenuItem:(NSMenuItem *)menuItem
126{
127    SEL sel;
128    NSAssert([menuItem target] == self, @"menu item does not target FSAController!");
129    sel = [menuItem action];
130    if (sel == @selector(showInfo:) || sel == @selector(createInterpreterWindow:) || sel == @selector(createBrowserForSelection:)) return YES;
131    FSALog(@"+[FSAController validateMenuItem:] unknown menu item for validation: %@", menuItem);
132    return NO;
133}
134
135+ (void)createInterpreterWindow:(id)sender;
136{
137    [[self alloc] initShowingInterpreter:YES];
138}
139
140+ (void)createBrowserForSelection:(id)sender;
141{
142    [[[self alloc] initShowingInterpreter:NO] FSA_associateAndOpenBrowser:sender];
143}
144
145+ (void)showInfo:(id)sender;
146{
147    int result = NSRunInformationalAlertPanel([NSString stringWithFormat: @"About F-Script Anywhere (version %s)", FSA_VERSION], @"F-Script Anywhere lets you embed a F-Script interpreter in a Cocoa application while it is running.\n\nF-Script Anywhere is currently installed in this application.  To remove it, quit this application.\n\nFor more information about F-Script, please visit its Web site %@.", @"OK", @"Visit Web Site", nil, FSA_FScriptURL);
148    if (result == NSAlertAlternateReturn) {
149        [[NSWorkspace sharedWorkspace] openURL: [NSURL URLWithString: FSA_FScriptURL]];
150    }
151}
152
153- (id)initShowingInterpreter:(BOOL)showInterpreter {
154    self = [super initWithWindowNibName: @"FSAInterpreterPanel"];
155   
156    if (self != nil) {
157        NSWindow *window = [self window];
158        NSString *label;
159        static unsigned numInterpWindows = 0;
160       
161        if (showInterpreter) {
162            NSAssert(window != nil, @"Can't get interpreter window!");
163            if ([window respondsToSelector: @selector(setBottomCornerRounded:)])
164                [window setBottomCornerRounded: NO]; // XXX otherwise we get black areas because the window isn't rounded
165            [window setContentBorderThickness: 30 forEdge: NSMinYEdge];
166            // XXX why oh why is text not vertically centered in standard-sized buttons?
167            [openBrowserButton setFrameSize: NSMakeSize([openBrowserButton frame].size.width, 19)];
168            [associateWithInterfaceButton setFrameSize: NSMakeSize([associateWithInterfaceButton frame].size.width, 19)];
169            [floatButtonCell setBackgroundStyle: NSBackgroundStyleRaised];
170            if (interpreterNum == 0) interpreterNum = ++numInterpWindows;
171            if ( (label = [self interpreterLabel]) != nil) {
172                [window setTitle: [NSString stringWithFormat: @"%@: %@", [window title], label]];
173            }
174           
175            [window setLevel: NSNormalWindowLevel]; // XXX if set floating, it is globally floating!
176            [self showWindow: self];
177            [window makeKeyAndOrderFront: self];
178#warning this should go away when F-Script properly accepts firstResponder on the InterpreterView
179            [window makeFirstResponder: (NSView *)[[[self interpreterView] cliView] shellView]];
180            [[FSAWindowManager sharedManager] registerWindow: window];
181        }
182        system = [[[self interpreterView] interpreter] objectForIdentifier: @"sys" found: NULL];
183        [system retain];
184        NSAssert1([system isKindOfClass: [System class]], @"Initial value bound to identifier 'sys' is not a System object, but %@", system);
185    }
186   
187    return self;
188}
189
190- (void)dealloc;
191{
192    [system release];
193    [super dealloc];
194}
195
196- (NSString *)interpreterLabel;
197{
198    static NSString *appName = nil;
199    static BOOL retrievedAppName = NO;
200   
201    if (appName == nil) {
202        if (retrievedAppName) return nil;
203        NS_DURING
204            appName = [[[NSBundle mainBundle] infoDictionary] objectForKey: @"CFBundleName"];
205        NS_HANDLER
206            FSALog(@"Exception occurred while trying to obtain application name: %@", localException);
207        NS_ENDHANDLER
208        retrievedAppName = YES;
209    }
210    if (interpreterNum == 1) return appName;
211    return [NSString stringWithFormat: @"%@ [%u]", appName, interpreterNum];
212}
213
214- (FSInterpreterView *)interpreterView;
215{
216    return interpreterView;
217}
218
219- (System *)system;
220{
221    return system;
222}
223
224- (IBAction)setFloating:(id)sender;
225{
226    [[self window] setLevel: [sender state] == NSOnState ? NSFloatingWindowLevel : NSNormalWindowLevel];
227}
228
229- (IBAction)FSA_associateAndOpenBrowser:(id)sender
230{
231    if (viewAssociationController == nil) {
232        viewAssociationController = [[FSAViewAssociationController alloc] initWithFSAController: self];
233    }
234    [viewAssociationController captureOneView];
235}
236
237@end
238
239@implementation FSAController (NSWindowDelegate)
240
241- (BOOL)windowShouldClose:(id)sender;
242{
243    NSEvent *e = [NSApp currentEvent];
244   
245    if ([e type] == NSKeyDown && [e keyCode] == 53) // Escape
246        return NO;
247   
248    return YES;
249}
250
251@end
Note: See TracBrowser for help on using the repository browser.