source: trunk/Cocoa/F-Script Anywhere/Source/FSAViewAssociationController.m@ 181

Last change on this file since 181 was 153, checked in by Nicholas Riley, 21 years ago

Integrates SCPatch and mach_inject; unfinished, buggy.

File size: 11.1 KB
RevLine 
[7]1//
2// FSAViewAssociationController.m
3// F-Script Anywhere
4//
5// Created by Nicholas Riley on Wed Jul 17 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 "FSAViewAssociationController.h"
[14]28#import "FSAController.h"
[19]29#import "FSAWindowManager.h"
[14]30#import "FSAnywhere.h"
31#import <FScript/FSInterpreter.h>
32#import <FScript/System.h>
[7]33
34@implementation FSAViewAssociationController
35
[14]36- (id)initWithFSAController:(FSAController *)fsa;
[7]37{
38 self = [super initWithWindowNibName: @"FSAViewAssociationPanel"];
39
40 if (self != nil) {
[19]41 NSImage *bullseyeImage = [[NSImage alloc] initByReferencingFile: [[NSBundle bundleForClass: [self class]] pathForResource: @"Bullseye menu cursor" ofType: @"tiff"]];
42 NSString *label = [fsa interpreterLabel];
43
[14]44 interpreter = [[[fsa interpreterView] interpreter] retain];
45 system = [fsa system];
[19]46 [[self window] setResizeIncrements: NSMakeSize(1, 12)];
47 if (label != nil) [[self window] setTitle: [NSString stringWithFormat: @"%@: %@", [[self window] title], label]];
48 bullseyeCursor = [[NSCursor alloc] initWithImage: bullseyeImage hotSpot: NSMakePoint(6, 7)];
[7]49 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(controlTextDidChange:) name: NSControlTextDidChangeNotification object: variableNameField];
[14]50 [[captureButton cell] setShowsStateBy: NSContentsCellMask | NSChangeGrayCellMask];
[19]51 [captureButton setState: NSOffState];
[7]52 [self update: nil];
53 }
54 return self;
55}
56
57- (void)dealloc;
58{
59 [viewHierarchyMenu release];
[19]60 [selectedElement release];
[7]61 [interpreter release];
[19]62 [bullseyeCursor release];
[7]63 [[NSNotificationCenter defaultCenter] removeObserver: self];
64 [super dealloc];
65}
66
67- (IBAction)update:(id)sender;
68{
[14]69 NSString *variableName = [variableNameField stringValue];
70 BOOL canAssignToVariable = NO;
[19]71 [browseButton setEnabled: selectedElement != nil];
[14]72 [statusField setStringValue: @""];
73 if ([variableName length] != 0) {
[153]74 if (![FSInterpreter validateSyntaxForIdentifier: variableName]) {
[14]75 [statusField setStringValue: @"Invalid name: contains spaces, punctuation or non-ASCII characters"];
[19]76 } else if (selectedElement != nil) {
[14]77 [statusField setStringValue: @"Click ÒAssociateÓ to assign to this variable"];
78 canAssignToVariable = YES;
79 }
80 }
81 [associateButton setEnabled: canAssignToVariable];
[7]82 [variableNameField setEnabled: [captureButton state] == NSOffState];
83}
84
[19]85- (void)stopCapturingVoluntarily:(BOOL)voluntary;
[7]86{
[14]87 FSALog(@"stopping capture");
[19]88 [[NSNotificationCenter defaultCenter] removeObserver: self name: NSMenuWillSendActionNotification object: nil];
[7]89 [captureButton setState: NSOffState];
90 [self update: nil];
[19]91 if (voluntary) {
92 FSALog(@"voluntary!");
93 [[self window] makeKeyAndOrderFront: self];
94 [bullseyeCursor pop];
95 [variableNameField becomeFirstResponder];
96 }
[7]97}
98
[153]99- (void)_addElement:(id)element withLabel:(NSString *)label toSubmenuForItem:(id<NSMenuItem>)item;
[19]100{
101 NSMenu *submenu = [item submenu];
[153]102 id<NSMenuItem> subItem;
[19]103 if (submenu == nil) {
104 id superElement = [item representedObject];
105 submenu = [[NSMenu alloc] initWithTitle: @""];
106 subItem = [submenu addItemWithTitle: NSStringFromClass([superElement class])
107 action: @selector(elementSelected:)
108 keyEquivalent: @""];
109 [subItem setTarget: self];
110 [subItem setRepresentedObject: superElement];
111 [item setSubmenu: submenu];
112 [submenu release];
113 }
114 [submenu addItem: [NSMenuItem separatorItem]];
115 [submenu addItemWithTitle: label action: nil keyEquivalent: @""];
116 subItem = [submenu addItemWithTitle: [@" "
117 stringByAppendingString: NSStringFromClass([element class])]
118 action: @selector(elementSelected:)
119 keyEquivalent: @""];
120 [subItem setTarget: self];
121 [subItem setRepresentedObject: element];
122}
123
[153]124- (void)_addValueForSelector:(SEL)sel withLabel:(NSString *)label toSubmenuForItem:(id<NSMenuItem>)item;
[19]125{
126 id obj = [item representedObject];
127 if ([obj respondsToSelector: sel]) {
128 id value = [obj performSelector: sel];
129 if (value == nil) return;
130 [self _addElement: value withLabel: label toSubmenuForItem: item];
131 }
132}
133
[14]134- (void)_addElementToMenu:(id)element;
135{
[153]136 id<NSMenuItem> item;
[14]137 if (element == nil) return;
138 item = [viewHierarchyMenu addItemWithTitle: [@" "
139 stringByAppendingString: NSStringFromClass([element class])]
140 action: @selector(elementSelected:)
141 keyEquivalent: @""];
142 [item setTarget: self];
143 [item setRepresentedObject: element];
[19]144 [self _addValueForSelector: @selector(windowController) withLabel: @"Window Controller" toSubmenuForItem: item];
145 [self _addValueForSelector: @selector(delegate) withLabel: @"Delegate" toSubmenuForItem: item];
146 [self _addValueForSelector: @selector(dataSource) withLabel: @"Data Source" toSubmenuForItem: item];
147 [self _addValueForSelector: @selector(target) withLabel: @"Target" toSubmenuForItem: item];
148 [self _addValueForSelector: @selector(cell) withLabel: @"Cell" toSubmenuForItem: item];
[14]149}
150
[7]151- (void)captureOneView;
152{
153 NSEvent *event;
154 NSView *view, *superView = nil, *contentView;
155 NSWindow *eventWindow;
[19]156 static unsigned captureCount = 0;
157 unsigned capture = captureCount++;
158
159 FSALog(@"%4u>capturing one", capture);
[14]160 [captureButton setState: NSOnState];
[19]161 [bullseyeCursor push];
[14]162
[19]163captureElement:
164 [bullseyeCursor set];
165 FSALog(@"%4u waiting for event...", capture);
166 [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(menuWillSendAction:) name: NSMenuWillSendActionNotification object: nil];
167 event = [NSApp nextEventMatchingMask: NSLeftMouseDownMask | NSRightMouseDownMask | NSOtherMouseDownMask | NSKeyUpMask | NSAppKitDefinedMask
[7]168 untilDate: [NSDate distantFuture]
169 inMode: NSEventTrackingRunLoopMode
170 dequeue: YES];
[19]171 FSALog(@"%4u got %@", capture, event);
172 [[NSNotificationCenter defaultCenter] removeObserver: self name: NSMenuWillSendActionNotification object: nil];
173 if ([event type] == NSAppKitDefined) {
174 if ([event subtype] == NSApplicationDeactivatedEventType) {
175 [NSApp discardEventsMatchingMask: NSAnyEventMask beforeEvent: event];
176 [self stopCapturingVoluntarily: NO];
177 [NSApp sendEvent: event];
178 return;
179 }
180 goto captureElement;
181 }
[7]182 if ([event type] == NSKeyUp) {
[19]183 [NSApp discardEventsMatchingMask: NSAnyEventMask & ~NSKeyUpMask beforeEvent: event];
184 FSALog(@"%4u<stop capture [key up]", capture);
185 [self stopCapturingVoluntarily: YES];
[7]186 return;
187 }
188 [viewHierarchyMenu release]; viewHierarchyMenu = nil;
189 viewHierarchyMenu = [[NSMenu alloc] initWithTitle: @""];
190 NS_DURING
191 eventWindow = [event window];
192 contentView = [eventWindow contentView];
193 view = [[contentView superview] hitTest: [event locationInWindow]];
194 if (view == captureButton) {
[19]195 [NSApp discardEventsMatchingMask: NSAnyEventMask & ~NSKeyUpMask beforeEvent: event];
196 FSALog(@"%4u<stop capture [capture button]", capture);
197 [self stopCapturingVoluntarily: YES];
[7]198 NS_VOIDRETURN;
199 }
[19]200 if (view == nil) {
201 [self captureOneView];
202 NS_VOIDRETURN;
203 }
[14]204 [viewHierarchyMenu addItemWithTitle: @"View" action: nil keyEquivalent: @""];
205 [self _addElementToMenu: view];
206 superView = view;
[7]207 do {
[14]208 superView = [superView superview];
[7]209 if (superView == nil) break;
[14]210 [self _addElementToMenu: superView];
[7]211 } while (superView != contentView);
212 [viewHierarchyMenu addItem: [NSMenuItem separatorItem]];
[14]213 [viewHierarchyMenu addItemWithTitle: @"Window" action: nil keyEquivalent: @""];
214 [self _addElementToMenu: eventWindow];
[7]215 NS_HANDLER
216 [descriptionField setStringValue:
217 [NSString stringWithFormat: @"Çan exception occurred: %@È", localException]];
218 NS_ENDHANDLER
219 [NSMenu popUpContextMenu: viewHierarchyMenu withEvent: event forView: view];
[19]220 if ([captureButton state] == NSOnState) goto captureElement;
221 FSALog(@"%4u<stop capture [fell through to end]", capture);
[7]222}
223
224- (IBAction)captureView:(id)sender
225{
[14]226 [statusField setStringValue: @"Click inside one of this applicationÕs windows to select."];
[19]227 [selectedElement release]; selectedElement = nil;
[7]228 [self update: nil];
229 [self captureOneView];
230}
231
[19]232- (void)setSelectedElement:(id)element;
[7]233{
[19]234 FSALog(@"element selected: %@", element);
[7]235 NS_DURING
[14]236 [descriptionField setStringValue: [element description]];
[19]237 [selectedElement release];
238 selectedElement = [element retain];
239 [[self window] orderFront: self];
[7]240 NS_HANDLER
241 [descriptionField setStringValue:
242 [NSString stringWithFormat: @"Çan exception occurred: %@È", localException]];
243 NS_ENDHANDLER
244 [viewHierarchyMenu release]; viewHierarchyMenu = nil;
[19]245}
246
247- (void)elementSelected:(NSMenuItem *)sender;
248{
249 [self setSelectedElement: [sender representedObject]];
[7]250 [self captureOneView];
251}
252
[19]253- (void)menuWillSendAction:(NSNotification *)notification;
254{
255 NSMenuItem *item = [[notification userInfo] objectForKey: @"MenuItem"];
256 [self setSelectedElement: item];
257 [NSApp discardEventsMatchingMask: NSAnyEventMask beforeEvent: [NSApp currentEvent]];
258 // we're already capturing, don't do it again
259}
260
261- (void)controlTextDidChange:(NSNotification *)notification;
262{
263 [self update: nil];
264}
265
[14]266- (IBAction)defineVariable:(id)sender;
[7]267{
268 NS_DURING
269 NSString *variableName = [variableNameField stringValue];
[14]270 [statusField setStringValue: @"AssociatingÉ"];
[19]271 [interpreter setObject: selectedElement forIdentifier: variableName];
[7]272 [statusField setStringValue: [NSString stringWithFormat: @"Assigned variable Ò%@Ó", variableName]];
273 NS_HANDLER
274 [statusField setStringValue: [NSString stringWithFormat: @"Assocation failed: %@", localException]];
275 NS_ENDHANDLER
276}
277
[14]278- (IBAction)viewInObjectBrowser:(id)sender;
279{
280 FSALog(@"system: %@", system);
[19]281 [system browse: selectedElement];
[14]282 [statusField setStringValue: @"Opened object browser"];
283}
284
[19]285@end
Note: See TracBrowser for help on using the repository browser.