JavaScriptCore:
authorthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Apr 2006 05:38:19 +0000 (05:38 +0000)
committerthatcher <thatcher@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Sat, 15 Apr 2006 05:38:19 +0000 (05:38 +0000)
        Reviewed by Timothy.

        Bug 8389: support for Cocoa bindings - binding an NSTreeController to the WebView's DOM
        http://bugzilla.opendarwin.org/show_bug.cgi?id=8389

        Adds a category to WebScriptObject with array accessors for KVC/KVO.

        If super valueForKey: fails it will call valueForUndefinedKey:, which is
        important because it causes the right behavior to happen with bindings using
        the "Raises for Not Applicable Keys" flag and the "Not Applicable Placeholder"

        * bindings/objc/WebScriptObject.mm:
        (-[WebScriptObject valueForKey:]):
        (-[WebScriptObject count]):
        (-[WebScriptObject objectAtIndex:]):
        (-[WebUndefined description]): return "undefined"

WebKit:

        Reviewed by Timothy.

        Bug 8389: support for Cocoa bindings - binding an NSTreeController to the WebView's DOM
        http://bugzilla.opendarwin.org/show_bug.cgi?id=8389

        Added a controller class, WebController, that is a subclass of
        NSTreeController that has a new outlet/binding for the WebView.

        * WebCoreSupport/WebFrameBridge.m:
        (-[WebFrameBridge windowObjectCleared]): notify bindings about the document change
        * WebView/WebView.m:
        (-[WebView _progressStarted:]): notify bindings about the document change
        (-[WebView _finalProgressComplete]): notify bindings about the document change
        (-[WebView _declaredKeys]): added a key for the main frame document
        (-[WebController init]):
        (-[WebController exposedBindings]):
        (-[WebController valueClassForBinding:]):
        (-[WebController setContent:]):
        (-[WebController webView]):
        (-[WebController setWebView:]):
        (-[WebView mainFrameDocument]): get the main frame's DOMDocument
        * WebView/WebViewPrivate.h: Adds mainFrameDocument to pending public.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@13877 268f45cc-cd09-0410-ab3c-d52691b4dbfc

JavaScriptCore/ChangeLog
JavaScriptCore/bindings/objc/WebScriptObject.mm
WebKit/ChangeLog
WebKit/WebCoreSupport/WebFrameBridge.m
WebKit/WebView/WebView.m
WebKit/WebView/WebViewPrivate.h

index 5d4b894..fbbd1f9 100644 (file)
@@ -1,3 +1,22 @@
+2006-04-14  James G. Speth  <speth@end.com>
+
+        Reviewed by Timothy.
+
+        Bug 8389: support for Cocoa bindings - binding an NSTreeController to the WebView's DOM
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=8389
+
+        Adds a category to WebScriptObject with array accessors for KVC/KVO.
+
+        If super valueForKey: fails it will call valueForUndefinedKey:, which is
+        important because it causes the right behavior to happen with bindings using
+        the "Raises for Not Applicable Keys" flag and the "Not Applicable Placeholder"
+
+        * bindings/objc/WebScriptObject.mm:
+        (-[WebScriptObject valueForKey:]):
+        (-[WebScriptObject count]):
+        (-[WebScriptObject objectAtIndex:]):
+        (-[WebUndefined description]): return "undefined"
+
 2006-04-13  Geoffrey Garen  <ggaren@apple.com>
 
         Reviewed by Darin.
index 5023a52..9b4711e 100644 (file)
@@ -283,6 +283,8 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     }
 
     id resultObj = [WebScriptObject _convertValueToObjcValue:result originExecutionContext:[self _originExecutionContext] executionContext:[self _executionContext]];
+    if ([resultObj isKindOfClass:[WebUndefined class]])
+        resultObj = [super valueForKey:key];    // ensure correct not-applicable key behavior
 
     _didExecute(self);
     
@@ -422,6 +424,31 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
 
 @end
 
+@interface WebScriptObject (WebKitCocoaBindings)
+
+- (unsigned int)count;
+- (id)objectAtIndex:(unsigned int)index;
+
+@end
+
+@implementation WebScriptObject (WebKitCocoaBindings)
+
+- (unsigned int)count
+{
+    id length = [self valueForKey:@"length"];
+    if ([length respondsToSelector:@selector(intValue)])
+        return [length intValue];
+    else
+        return 0;
+}
+
+- (id)objectAtIndex:(unsigned int)index
+{
+    return [self webScriptValueAtIndex:index];
+}
+
+@end
+
 @implementation WebUndefined
 
 + (id)allocWithZone:(NSZone *)zone
@@ -433,6 +460,11 @@ static List listFromNSArray(ExecState *exec, NSArray *array)
     return sharedUndefined;
 }
 
+- (NSString *)description
+{
+    return @"undefined";
+}
+
 - (id)initWithCoder:(NSCoder *)coder
 {
     UNUSED_PARAM(coder);
index e04d580..cb37c14 100644 (file)
@@ -1,3 +1,28 @@
+2006-04-14  James G. Speth  <speth@end.com>
+
+        Reviewed by Timothy.
+
+        Bug 8389: support for Cocoa bindings - binding an NSTreeController to the WebView's DOM
+        http://bugzilla.opendarwin.org/show_bug.cgi?id=8389
+
+        Added a controller class, WebController, that is a subclass of
+        NSTreeController that has a new outlet/binding for the WebView.
+
+        * WebCoreSupport/WebFrameBridge.m:
+        (-[WebFrameBridge windowObjectCleared]): notify bindings about the document change
+        * WebView/WebView.m:
+        (-[WebView _progressStarted:]): notify bindings about the document change
+        (-[WebView _finalProgressComplete]): notify bindings about the document change
+        (-[WebView _declaredKeys]): added a key for the main frame document
+        (-[WebController init]):
+        (-[WebController exposedBindings]):
+        (-[WebController valueClassForBinding:]):
+        (-[WebController setContent:]):
+        (-[WebController webView]):
+        (-[WebController setWebView:]):
+        (-[WebView mainFrameDocument]): get the main frame's DOMDocument
+        * WebView/WebViewPrivate.h: Adds mainFrameDocument to pending public.
+
 2006-04-12  David Harrison  <harrison@apple.com>
 
         Reviewed by Darin.
index c314ff3..7cccc5b 100644 (file)
@@ -1496,6 +1496,10 @@ static id <WebFormDelegate> formDelegate(WebFrameBridge *self)
 {
     WebView *wv = [self webView];
     [[wv _frameLoadDelegateForwarder] webView:wv windowScriptObjectAvailable:[self windowScriptObject]];
+    // this KVO notification first started in WebView's _progressStarted:, and gets finished here
+    [wv _didChangeValueForKey:_WebMainFrameDocumentKey];
+    // start another change notification that will be completed in WebView's _finalProgressComplete:
+    [wv _willChangeValueForKey:_WebMainFrameDocumentKey];
     if ([wv scriptDebugDelegate]) {
         [_frame _attachScriptDebugger];
     }
index af6d7a1..0c779ae 100644 (file)
@@ -345,6 +345,7 @@ NSString *_WebIsLoadingKey =            @"isLoading";
 NSString *_WebMainFrameIconKey =        @"mainFrameIcon";
 NSString *_WebMainFrameTitleKey =       @"mainFrameTitle";
 NSString *_WebMainFrameURLKey =         @"mainFrameURL";
+NSString *_WebMainFrameDocumentKey =    @"mainFrameDocument";
 
 @interface WebProgressItem : NSObject
 {
@@ -1038,6 +1039,7 @@ static bool debugWidget = true;
         _private->progressValue = INITIAL_PROGRESS_VALUE;
         _private->originatingProgressFrame = [frame retain];
         [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressStartedNotification object:self];
+        [self _willChangeValueForKey:_WebMainFrameDocumentKey];     // paired with didChange.. in windowObjectCleared
     }
     _private->numProgressTrackedFrames++;
     [self _didChangeValueForKey: @"estimatedProgress"];
@@ -1052,6 +1054,8 @@ static bool debugWidget = true;
     if (!_private->finalProgressChangedSent) {
         _private->progressValue = 1;
         [[NSNotificationCenter defaultCenter] postNotificationName:WebViewProgressEstimateChangedNotification object:self];
+        // send the final KVO message, ending the willChange.. from WebFrameBridge windowObjectCleared
+        [self _didChangeValueForKey:_WebMainFrameDocumentKey];
     }
     
     [self _resetProgress];
@@ -1186,7 +1190,7 @@ static bool debugWidget = true;
     static NSArray *declaredKeys = nil;
     
     if (!declaredKeys) {
-        declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, nil];
+        declaredKeys = [[NSArray alloc] initWithObjects:_WebMainFrameURLKey, _WebIsLoadingKey, _WebEstimatedProgressKey, _WebCanGoBackKey, _WebCanGoForwardKey, _WebMainFrameTitleKey, _WebMainFrameIconKey, _WebMainFrameDocumentKey, nil];
     }
 
     return declaredKeys;
@@ -2520,6 +2524,82 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
 
 @end
 
+@implementation WebController
+
+- (id)init
+{
+    self = [super init];
+    if (self == nil)
+        return nil;
+    [self setChildrenKeyPath:@"childNodes"];
+    [self setObjectClass:[DOMNode class]];
+    return self;
+}
+
+- (NSArray *)exposedBindings
+{
+    NSArray *bindings = [super exposedBindings];
+    return [bindings arrayByAddingObject:@"webView"];
+}
+
+- (Class)valueClassForBinding:(NSString *)binding
+{
+    if ([binding isEqualToString:@"webView"])
+        return [WebView class];
+    return [super valueClassForBinding:binding];
+}
+
+- (void)setContent:(id)newContent
+{
+    // override NSTreeController's setContent: to prevent crash when changing the tree
+    //   see http://www.cocoadev.com/index.pl?NSTreeControllerBugOrDeveloperError
+    
+    // in our case, it prevents a crash in NSTreeController that occurs when:
+    // 1. an outline view has a column bound to arrangedObjects.nodeName
+    // 2. a text field has its value bound to selection.innerHTML
+    // 3. a node is selected in the outline view
+    // 4. a new page is loaded in the WebView
+    //    -> crash
+    // step 3 is necessary for the crash, it does not happen when there's no selection
+    
+    // retain original values while the content changes
+    id content = [[self content] retain];
+    NSArray *paths = [[self selectionIndexPaths] retain];
+    NSString *childrenKeyPath = [[self childrenKeyPath] retain];
+    
+    // clear the tree controller state as much as possible
+    [self setSelectionIndexPaths:nil];
+    [super setContent:nil];
+    
+    // set the new content and restore the configuration
+    [super setContent:newContent];
+    [self setChildrenKeyPath:childrenKeyPath];
+    [self setSelectionIndexPaths:paths];
+    
+    // release the original content and the temporary storage
+    [content release];
+    [paths release];
+    [childrenKeyPath release];
+}
+
+- (WebView *)webView
+{
+    return [[webView retain] autorelease];
+}
+
+- (void)setWebView:(WebView *)newWebView
+{
+    if (newWebView == webView)
+        return;
+    [self unbind:@"contentObject"];
+    id old = webView;
+    webView = [newWebView retain];
+    [old release];
+    [self bind:@"contentObject" toObject:webView withKeyPath:_WebMainFrameDocumentKey options:nil];
+}
+
+@end
+
 @implementation WebView (WebPendingPublic)
 
 - (void)setMainFrameURL:(NSString *)URLString
@@ -2553,6 +2633,11 @@ static WebFrame *incrementFrame(WebFrame *curr, BOOL forward, BOOL wrapFlag)
     return [[WebIconDatabase sharedIconDatabase] iconForURL:[[[[self mainFrame] dataSource] _URL] _web_originalDataAsString] withSize:WebIconSmallSize];
 }
 
+- (DOMDocument *)mainFrameDocument
+{
+    return [[self mainFrame] DOMDocument];
+}
+
 - (void)setDrawsBackground:(BOOL)drawsBackground
 {
     if (_private->drawsBackground == drawsBackground)
index 6dbc4ed..ccc8547 100644 (file)
@@ -64,6 +64,7 @@ extern NSString *_WebIsLoadingKey;
 extern NSString *_WebMainFrameIconKey;
 extern NSString *_WebMainFrameTitleKey;
 extern NSString *_WebMainFrameURLKey;
+extern NSString *_WebMainFrameDocumentKey;
 
 extern NSString *WebElementTitleKey;   // NSString of the title of the element (pending public, used by Safari)
 
@@ -74,6 +75,12 @@ typedef enum {
     WebDashboardBehaviorAllowWheelScrolling
 } WebDashboardBehavior;
 
+@interface WebController : NSTreeController {
+    IBOutlet WebView *webView;
+}
+- (WebView *)webView;
+- (void)setWebView:(WebView *)newWebView;
+@end
 
 @interface WebView (WebPendingPublic)
 
@@ -82,6 +89,7 @@ typedef enum {
 - (BOOL)isLoading;
 - (NSString *)mainFrameTitle;
 - (NSImage *)mainFrameIcon;
+- (DOMDocument *)mainFrameDocument;
 
 - (void)setDrawsBackground:(BOOL)drawsBackround;
 - (BOOL)drawsBackground;