// // FSAViewAssociationController.m // F-Script Anywhere // // Created by Nicholas Riley on Wed Jul 17 2002. // Copyright (c) 2002 Nicholas Riley. All rights reserved. // /* F-Script Anywhere is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. F-Script Anywhere is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with F-Script Anywhere; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #import "FSAViewAssociationController.h" #import "FSAController.h" #import "FSAnywhere.h" #import #import // XXX workaround for lack of identifier validation; should go away when F-Script adds (promised) direct support for this @interface Compiler + (BOOL)isValidIndentifier:(NSString *)str; @end @implementation FSAViewAssociationController - (id)initWithFSAController:(FSAController *)fsa; { self = [super initWithWindowNibName: @"FSAViewAssociationPanel"]; if (self != nil) { interpreter = [[[fsa interpreterView] interpreter] retain]; system = [fsa system]; [self window]; [[NSNotificationCenter defaultCenter] addObserver: self selector: @selector(controlTextDidChange:) name: NSControlTextDidChangeNotification object: variableNameField]; [[captureButton cell] setShowsStateBy: NSContentsCellMask | NSChangeGrayCellMask]; [self update: nil]; } return self; } - (void)dealloc; { [viewHierarchyMenu release]; [selectedView release]; [interpreter release]; [[NSNotificationCenter defaultCenter] removeObserver: self]; [super dealloc]; } - (IBAction)update:(id)sender; { NSString *variableName = [variableNameField stringValue]; BOOL canAssignToVariable = NO; [browseButton setEnabled: selectedView != nil]; [statusField setStringValue: @""]; if ([variableName length] != 0) { if (![Compiler isValidIndentifier: variableName]) { [statusField setStringValue: @"Invalid name: contains spaces, punctuation or non-ASCII characters"]; } else if (selectedView != nil) { [statusField setStringValue: @"Click ÒAssociateÓ to assign to this variable"]; canAssignToVariable = YES; } } [associateButton setEnabled: canAssignToVariable]; [variableNameField setEnabled: [captureButton state] == NSOffState]; } - (void)stopCapturing; { FSALog(@"stopping capture"); [captureButton setState: NSOffState]; [statusField setStringValue: @""]; [self update: nil]; [variableNameField becomeFirstResponder]; } - (void)_addElementToMenu:(id)element; { NSMenuItem *item; if (element == nil) return; item = [viewHierarchyMenu addItemWithTitle: [@" " stringByAppendingString: NSStringFromClass([element class])] action: @selector(elementSelected:) keyEquivalent: @""]; [item setTarget: self]; [item setRepresentedObject: element]; } - (void)captureOneView; { NSEvent *event; NSView *view, *superView = nil, *contentView; NSWindow *eventWindow; FSALog(@"capturing one"); [captureButton setState: NSOnState]; event = [NSApp nextEventMatchingMask: NSLeftMouseDownMask | NSRightMouseDownMask | NSKeyUpMask untilDate: [NSDate distantFuture] inMode: NSEventTrackingRunLoopMode dequeue: YES]; if ([event type] == NSKeyUp) { [self stopCapturing]; return; } [viewHierarchyMenu release]; viewHierarchyMenu = nil; viewHierarchyMenu = [[NSMenu alloc] initWithTitle: @""]; NS_DURING eventWindow = [event window]; contentView = [eventWindow contentView]; view = [[contentView superview] hitTest: [event locationInWindow]]; if (view == captureButton) { [self stopCapturing]; NS_VOIDRETURN; } [viewHierarchyMenu addItemWithTitle: @"View" action: nil keyEquivalent: @""]; [self _addElementToMenu: view]; superView = view; do { superView = [superView superview]; if (superView == nil) break; [self _addElementToMenu: superView]; } while (superView != contentView); [viewHierarchyMenu addItem: [NSMenuItem separatorItem]]; [viewHierarchyMenu addItemWithTitle: @"Window" action: nil keyEquivalent: @""]; [self _addElementToMenu: eventWindow]; NS_HANDLER [descriptionField setStringValue: [NSString stringWithFormat: @"Çan exception occurred: %@È", localException]]; NS_ENDHANDLER [NSMenu popUpContextMenu: viewHierarchyMenu withEvent: event forView: view]; if ([captureButton state] == NSOnState) [self captureOneView]; } - (IBAction)captureView:(id)sender { [statusField setStringValue: @"Click inside one of this applicationÕs windows to select."]; [selectedView release]; selectedView = nil; [self update: nil]; [self captureOneView]; } - (void)elementSelected:(NSMenuItem *)sender; { NSView *element = [sender representedObject]; FSALog(@"element selected: %@", sender); NS_DURING [descriptionField setStringValue: [element description]]; [selectedView release]; selectedView = [element retain]; NS_HANDLER [descriptionField setStringValue: [NSString stringWithFormat: @"Çan exception occurred: %@È", localException]]; NS_ENDHANDLER [viewHierarchyMenu release]; viewHierarchyMenu = nil; [self captureOneView]; } - (IBAction)defineVariable:(id)sender; { #warning this should change when F-Script supports a public API for identifier validation NS_DURING NSString *variableName = [variableNameField stringValue]; [statusField setStringValue: @"AssociatingÉ"]; [interpreter setObject: selectedView forIdentifier: variableName]; [statusField setStringValue: [NSString stringWithFormat: @"Assigned variable Ò%@Ó", variableName]]; NS_HANDLER [statusField setStringValue: [NSString stringWithFormat: @"Assocation failed: %@", localException]]; NS_ENDHANDLER } - (IBAction)viewInObjectBrowser:(id)sender; { FSALog(@"system: %@", system); [system browse: selectedView]; [statusField setStringValue: @"Opened object browser"]; } - (void)controlTextDidChange:(NSNotification *)notification; { [self update: nil]; } @end