Index: trunk/Cocoa/F-Script Anywhere/Source/FSAViewAssociationController.m
===================================================================
--- trunk/Cocoa/F-Script Anywhere/Source/FSAViewAssociationController.m	(revision 7)
+++ trunk/Cocoa/F-Script Anywhere/Source/FSAViewAssociationController.m	(revision 14)
@@ -26,15 +26,26 @@
 
 #import "FSAViewAssociationController.h"
+#import "FSAController.h"
+#import "FSAnywhere.h"
+#import <FScript/FSInterpreter.h>
+#import <FScript/System.h>
+
+// 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)initWithInterpreter:(FSInterpreter *)anInterpreter;
+- (id)initWithFSAController:(FSAController *)fsa;
 {
     self = [super initWithWindowNibName: @"FSAViewAssociationPanel"];
 
     if (self != nil) {
-        interpreter = [anInterpreter retain];
+        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];
     }
@@ -53,5 +64,17 @@
 - (IBAction)update:(id)sender;
 {
-    [associateButton setEnabled: selectedView != nil && [[variableNameField stringValue] length] != 0];
+    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];
 }
@@ -59,8 +82,21 @@
 - (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];
 }
 
@@ -70,5 +106,7 @@
     NSView *view, *superView = nil, *contentView;
     NSWindow *eventWindow;
-    NSMenuItem *item;
+
+    FSALog(@"capturing one");
+    [captureButton setState: NSOnState];
 
     event = [NSApp nextEventMatchingMask: NSLeftMouseDownMask | NSRightMouseDownMask | NSKeyUpMask
@@ -90,20 +128,15 @@
             NS_VOIDRETURN;
         }
+        [viewHierarchyMenu addItemWithTitle: @"View" action: nil keyEquivalent: @""];
+        [self _addElementToMenu: view];
+        superView = view;
         do {
-            if (superView == nil) superView = view;
-            else superView = [superView superview];
+            superView = [superView superview];
             if (superView == nil) break;
-            item = [viewHierarchyMenu addItemWithTitle: NSStringFromClass([superView class])
-                                                action: @selector(viewSelected:)
-                                         keyEquivalent: @""];
-            [item setTarget: self];
-            [item setRepresentedObject: superView];
+            [self _addElementToMenu: superView];
         } while (superView != contentView);
         [viewHierarchyMenu addItem: [NSMenuItem separatorItem]];
-        item = [viewHierarchyMenu addItemWithTitle: NSStringFromClass([eventWindow class])
-                                            action: @selector(viewSelected:)
-                                     keyEquivalent: @""];
-        [item setTarget: self];
-        [item setRepresentedObject: eventWindow];
+        [viewHierarchyMenu addItemWithTitle: @"Window" action: nil keyEquivalent: @""];
+        [self _addElementToMenu: eventWindow];
     NS_HANDLER
         [descriptionField setStringValue:
@@ -111,9 +144,11 @@
     NS_ENDHANDLER
     [NSMenu popUpContextMenu: viewHierarchyMenu withEvent: event forView: view];
+    if ([captureButton state] == NSOnState)
+        [self captureOneView];
 }
 
 - (IBAction)captureView:(id)sender
 {
-    [statusField setStringValue: @"Click to select; press any key to cancel."];
+    [statusField setStringValue: @"Click inside one of this applicationÕs windows to select."];
     [selectedView release]; selectedView = nil;
     [self update: nil];
@@ -121,11 +156,12 @@
 }
 
-- (void)viewSelected:(NSMenuItem *)sender;
+- (void)elementSelected:(NSMenuItem *)sender;
 {
-    NSView *view = [sender representedObject];
+    NSView *element = [sender representedObject];
+    FSALog(@"element selected: %@", sender);
     NS_DURING
-        [descriptionField setStringValue: [view description]];
+        [descriptionField setStringValue: [element description]];
         [selectedView release];
-        selectedView = [view retain];
+        selectedView = [element retain];
     NS_HANDLER
         [descriptionField setStringValue:
@@ -136,9 +172,10 @@
 }
 
-- (IBAction)defineVariable:(id)sender
+- (IBAction)defineVariable:(id)sender;
 {
-    [statusField setStringValue: @"AssociatingÉ"];
+#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]];
@@ -146,4 +183,11 @@
         [statusField setStringValue: [NSString stringWithFormat: @"Assocation failed: %@", localException]];
     NS_ENDHANDLER
+}
+
+- (IBAction)viewInObjectBrowser:(id)sender;
+{
+    FSALog(@"system: %@", system);
+    [system browse: selectedView];
+    [statusField setStringValue: @"Opened object browser"];
 }
 
