<binding destination="-2" name="contentArray" keyPath="_model.stack" id="myv-aO-biI"/>
</connections>
</arrayController>
- <treeController objectClassName="VariableNode" editable="NO" childrenKeyPath="dynamicChildren" leafKeyPath="isLeaf" id="59" userLabel="VariablesController">
+ <treeController objectClassName="VariableNode" editable="NO" childrenKeyPath="children" countKeyPath="childCount" leafKeyPath="isLeaf" id="59" userLabel="VariablesController">
<declaredKeys>
<string>value</string>
<string>name</string>
// Evaluates a given string in the current execution context.
- (void)evalScript:(NSString*)str callback:(void (^)(NSString*))callback;
-// Gets a property by name from the debugger engine. Properties must be
-// retrieved at a certain stack depth.
-- (void)getChildrenOfProperty:(VariableNode*)property
- atDepth:(NSInteger)depth
- callback:(void (^)(NSArray*))callback;
-
// Takes a partially loaded stack frame and fetches the rest of the information.
- (void)loadStackFrame:(StackFrame*)frame;
+// Ensures that a variable node's immediate children are loaded, and fetches
+// any that are not. This is done within the scope of the given stack frame.
+- (void)loadVariableNode:(VariableNode*)variable
+ forStackFrame:(StackFrame*)frame;
+
@end
// Delegate ////////////////////////////////////////////////////////////////////
self.status = @"Stopped";
}
-/**
- * Tells the debugger engine to get a specifc property. This also takes in the NSXMLElement
- * that requested it so that the child can be attached.
- */
-- (void)getChildrenOfProperty:(VariableNode*)property
- atDepth:(NSInteger)depth
- callback:(void (^)(NSArray*))callback {
- ProtocolClientMessageHandler handler = ^(NSXMLDocument* message) {
- /*
- <response>
- <property> <!-- this is the one we requested -->
- <property ... /> <!-- these are what we want -->
- </property>
- </repsonse>
- */
-
- // Detach all the children so we can insert them into another document.
- NSXMLElement* parent = (NSXMLElement*)[[message rootElement] childAtIndex:0];
- NSArray* children = [parent children];
- [parent setChildren:nil];
-
- callback(children);
- };
- [_client sendCommandWithFormat:@"property_get -d %d -n %@" handler:handler, depth, [property fullName]];
-}
-
- (void)loadStackFrame:(StackFrame*)frame {
if (frame.loaded)
return;
frame.loaded = YES;
}
+- (void)loadVariableNode:(VariableNode*)variable
+ forStackFrame:(StackFrame*)frame {
+ if (variable.children.count == variable.childCount)
+ return;
+
+ [self loadVariableNode:variable forStackFrame:frame dataPage:0 loadedData:@[]];
+}
+
+- (void)loadVariableNode:(VariableNode*)variable
+ forStackFrame:(StackFrame*)frame
+ dataPage:(unsigned int)dataPage
+ loadedData:(NSArray*)loadedData {
+ ProtocolClientMessageHandler handler = ^(NSXMLDocument* message) {
+ /*
+ <response>
+ <property> <!-- this is the one we requested -->
+ <property ... /> <!-- these are what we want -->
+ </property>
+ </repsonse>
+ */
+
+ // Detach all the children so we can insert them into another document.
+ NSXMLElement* parent = (NSXMLElement*)[[message rootElement] childAtIndex:0];
+ NSArray* children = [parent children];
+ [parent setChildren:nil];
+
+ // Check to see if there are more children to load.
+ NSArray* newLoadedData = [loadedData arrayByAddingObjectsFromArray:children];
+
+ unsigned int totalChildren = [[[parent attributeForName:@"numchildren"] stringValue] integerValue];
+ if ([newLoadedData count] < totalChildren) {
+ [self loadVariableNode:variable
+ forStackFrame:frame
+ dataPage:dataPage + 1
+ loadedData:newLoadedData];
+ } else {
+ [variable setChildrenFromXMLChildren:newLoadedData];
+ }
+ };
+ [_client sendCommandWithFormat:@"property_get -d %d -n %@ -p %u" handler:handler, frame.index, variable.fullName, dataPage];
+}
+
// Breakpoint Management ///////////////////////////////////////////////////////
#pragma mark Breakpoints
- (IBAction)stepOver:(id)sender;
- (IBAction)stop:(id)sender;
-- (void)fetchChildProperties:(VariableNode*)node;
-
@end
[connection stop];
}
-- (void)fetchChildProperties:(VariableNode*)node
-{
- NSArray* selection = [stackArrayController selectedObjects];
- if (![selection count])
- return;
- assert([selection count] == 1);
- NSInteger depth = [[selection objectAtIndex:0] index];
- [connection getChildrenOfProperty:node atDepth:depth callback:^(NSArray* properties) {
- [node setChildrenFromXMLChildren:properties];
- [variablesTreeController rearrangeObjects];
- }];
-}
-
/**
* NSTableView delegate method that informs the controller that the stack selection did change and that
* we should update the source viewer
{
NSTreeNode* node = [[notif userInfo] objectForKey:@"NSObject"];
[expandedVariables addObject:[[node representedObject] fullName]];
+
+ [connection loadVariableNode:[node representedObject]
+ forStackFrame:[[stackArrayController selectedObjects] lastObject]];
}
/**
// the children on a node from the list of children from the XML response.
- (void)setChildrenFromXMLChildren:(NSArray*)children;
-// Returns the children and requests any unloaded ones.
-- (NSArray*)dynamicChildren;
-
// Whether or not this is a leaf node (i.e. does not have child properties).
- (BOOL)isLeaf;
#import "VariableNode.h"
-#import "AppDelegate.h"
#include "NSXMLElementAdditions.h"
// Private Properties //////////////////////////////////////////////////////////
- (void)setChildrenFromXMLChildren:(NSArray*)children
{
+ [self willChangeValueForKey:@"children"];
+
+ [children_ removeAllObjects];
+
for (NSXMLNode* child in children) {
// Other child nodes may be the string value.
if ([child isKindOfClass:[NSXMLElement class]]) {
[node release];
}
}
-}
-- (NSArray*)dynamicChildren
-{
- NSArray* children = self.children;
- if (![self isLeaf] && (NSInteger)[children count] < self.childCount) {
- // If this node has children but they haven't been loaded from the backend,
- // request them asynchronously.
- [[AppDelegate instance].debugger fetchChildProperties:self];
- }
- return children;
+ [self didChangeValueForKey:@"children"];
}
- (BOOL)isLeaf