From: helge Date: Mon, 1 Aug 2005 12:13:13 +0000 (+0000) Subject: treeview refactoring X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=1859cc22b6219463baa39c67603a2911b6eb4768;p=sope treeview refactoring git-svn-id: http://svn.opengroupware.org/SOPE/trunk@954 e4a50df8-12e2-0310-a44c-efbce7f8a7e3 --- diff --git a/sope-appserver/WEExtensions/ChangeLog b/sope-appserver/WEExtensions/ChangeLog index b8fa5897..2080e5e0 100644 --- a/sope-appserver/WEExtensions/ChangeLog +++ b/sope-appserver/WEExtensions/ChangeLog @@ -1,3 +1,11 @@ +2005-08-01 Helge Hess + + * v4.5.79 + + * WETreeView.m: major code cleanups + + * WETreeMatrixElement.m: minor performance improvements + 2005-07-22 Marcus Mueller * JSStringTable.m: if 'if-none-match' is not set, do not return a 304 diff --git a/sope-appserver/WEExtensions/JSStringTable.m b/sope-appserver/WEExtensions/JSStringTable.m index ef8bfa62..d62815ff 100644 --- a/sope-appserver/WEExtensions/JSStringTable.m +++ b/sope-appserver/WEExtensions/JSStringTable.m @@ -103,7 +103,7 @@ if (isFirst) isFirst = NO; else [_response appendContentString:@",\n"]; - value = [_table objectForKey:key]; + value = [(NSDictionary *)_table objectForKey:key]; /* escape value */ value = [value stringByReplacingString:@"\"" withString:@"\\\""]; diff --git a/sope-appserver/WEExtensions/Version b/sope-appserver/WEExtensions/Version index 847ef478..df461f3d 100644 --- a/sope-appserver/WEExtensions/Version +++ b/sope-appserver/WEExtensions/Version @@ -1,6 +1,6 @@ # version file -SUBMINOR_VERSION:=78 +SUBMINOR_VERSION:=79 # v4.5.76 requires libNGObjWeb v4.5.176 # v4.5.75 requires libNGObjWeb v4.5.174 diff --git a/sope-appserver/WEExtensions/WETreeData.m b/sope-appserver/WEExtensions/WETreeData.m index 100a3c4c..572e1b76 100644 --- a/sope-appserver/WEExtensions/WETreeData.m +++ b/sope-appserver/WEExtensions/WETreeData.m @@ -58,7 +58,7 @@ WOAssociation *cornerIcon; WOAssociation *treeLink; - BOOL doTable; + BOOL doTable; // THREAD (used during generation) WOElement *template; } @@ -180,6 +180,8 @@ static Class StrClass = Nil; toResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { + /* this appends plus and minus images and links to expand/collapse */ + // TODO: explain more BOOL doLink; NSString *img; NSString *link; @@ -287,61 +289,77 @@ static Class StrClass = Nil; [_response appendContentString:@""]; } +- (void)appendPaddingCellsOfTreeElement:(id)treeElement + toResponse:(WOResponse *)_response + inContext:(WOContext *)_ctx +{ + /* + This renders all the tree-view related lines and plus/minus signs, + padding etc. + */ + unsigned int i; + + for (i = 0; i < [treeElement depth]+1; i++) { + NSString *iconWidth; + NSString *treeElm; + + iconWidth = [_ctx objectForKey:WETreeView_IconWidth]; + + treeElm = (i < [treeElement depth]) + ? [treeElement elementAtIndex:i] + : [treeElement leaf]; + + if (self->doTable) { + [_response appendContentString:@""]; + } + + /* this appends plus and minus images and links to expand/collapse */ + [self _appendTreeElement:treeElm toResponse:_response inContext:_ctx]; + + if (self->doTable) + [_response appendContentString:@""]; + } +} + - (void)appendData:(WOResponse *)_response inContext:(WOContext *)_ctx { /* TODO: split up this method */ _WETreeMatrixElement *treeElement; WOComponent *cmp = nil; BOOL isTree = NO; NSString *content = nil; - int i; - + cmp = [_ctx component]; isTree = [self->isTreeElement boolValueInComponent:cmp]; content = [self->string stringValueInComponent:cmp]; treeElement = [_ctx objectForKey:WETreeView_TreeElement]; if (isTree) { - for (i = 0; i < [treeElement depth]+1; i++) { - NSString *iconWidth; - NSString *treeElm; - - iconWidth = [_ctx objectForKey:WETreeView_IconWidth]; - - treeElm = (i < [treeElement depth]) - ? [treeElement elementAtIndex:i] - : [treeElement leaf]; - - if (self->doTable) { - [_response appendContentString:@""]; - } - - [self _appendTreeElement:treeElm toResponse:_response inContext:_ctx]; - if (self->doTable) - [_response appendContentString:@""]; - } + /* this is a first cell in a row, it renders the tree controls */ + [self appendPaddingCellsOfTreeElement:treeElement + toResponse:_response inContext:_ctx]; if (self->doTable) { [_response appendContentString:@""]; } else { // ! isTree + /* this is a follow-up cell in a row, it renders just the content */ if (self->doTable) { [_response appendContentString:@"template appendToResponse:_response inContext:_ctx]; - if (content) [_response appendContentHTMLString:content]; + if (content != nil) [_response appendContentHTMLString:content]; if (self->doTable) [_response appendContentString:@""]; } } +/* handle requests */ + - (void)takeValuesFromRequest:(WORequest *)_rq inContext:(WOContext *)_ctx { [self->template takeValuesFromRequest:_rq inContext:_ctx]; } @@ -391,8 +412,10 @@ static Class StrClass = Nil; return [self->template invokeActionForRequest:_rq inContext:_ctx]; } +/* generate response */ + - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { - self->doTable = ([_ctx objectForKey:WETreeView_RenderNoTable] == nil); + self->doTable = ([_ctx objectForKey:WETreeView_RenderNoTable] == nil)?YES:NO; if ([_ctx objectForKey:WETreeView_HEADER_MODE]) [self appendHeader:_response inContext:_ctx]; diff --git a/sope-appserver/WEExtensions/WETreeMatrixElement.h b/sope-appserver/WEExtensions/WETreeMatrixElement.h index b8bccda8..99faf9b3 100644 --- a/sope-appserver/WEExtensions/WETreeMatrixElement.h +++ b/sope-appserver/WEExtensions/WETreeMatrixElement.h @@ -24,7 +24,22 @@ #import -#define MAX_TREE_DEPTH 11 /* max recursion depth is 10 */ +/* + _WETreeMatrixElement + + This object represents a row in the table generated for the tree view. Prior + rendering the tree view iterates over the active list of nodes and collects + them as matrix-elements. The view needs to do this to calculate proper + colspans and lines. + + The 'elements' array contains the columns of the table, this includes markers + for the tree parts being rendered (lines, +/- etc). + + For rendering WETreeData retrieves the 'active' tree element from the context + using the 'WETreeView_TreeElement' key. +*/ + +#define MAX_TREE_DEPTH 21 /* max recursion depth is 20 */ @interface _WETreeMatrixElement : NSObject { diff --git a/sope-appserver/WEExtensions/WETreeMatrixElement.m b/sope-appserver/WEExtensions/WETreeMatrixElement.m index d4170c0a..84138159 100644 --- a/sope-appserver/WEExtensions/WETreeMatrixElement.m +++ b/sope-appserver/WEExtensions/WETreeMatrixElement.m @@ -103,9 +103,17 @@ static Class StrClass = Nil; } - (NSString *)colspanAsString { - char buf[8]; - sprintf(buf, "%d", self->colspan); - return [NSString stringWithCString:buf]; + switch (self->colspan) { + case 0: return @"0"; + case 1: return @"1"; + case 2: return @"2"; + case 3: return @"3"; + default: { + char buf[8]; + sprintf(buf, "%d", self->colspan); + return [StrClass stringWithCString:buf]; + } + } } - (int)depth { @@ -128,13 +136,16 @@ static Class StrClass = Nil; - (NSString *)elementID { // TODO: improve performance NSMutableArray *tmp; - NSString *s; - int i; + NSString *s; + unsigned int i; tmp = [[NSMutableArray alloc] initWithCapacity:self->depth]; for (i = 0; i < self->depth; i++) { - s = [[StrClass alloc] initWithFormat:@"%d", self->indexPath[i]]; + char buf[8]; + + sprintf(buf, "%d", self->indexPath[i]); + s = [[StrClass alloc] initWithCString:buf]; [tmp addObject:s]; [s release]; } diff --git a/sope-appserver/WEExtensions/WETreeView.m b/sope-appserver/WEExtensions/WETreeView.m index fe4a156d..f0b6e3ad 100644 --- a/sope-appserver/WEExtensions/WETreeView.m +++ b/sope-appserver/WEExtensions/WETreeView.m @@ -147,8 +147,6 @@ #include -@class NSMutableArray; - @interface WETreeView : WODynamicElement { // WODynamicElement: extraAttributes @@ -177,9 +175,6 @@ WOAssociation *lineIcon; WOAssociation *spaceIcon; WOAssociation *iconWidth; - - // private: - NSMutableArray *matrix; WOElement *template; } @@ -270,7 +265,6 @@ NSString *WETreeView_Space = @"WETreeView_Space"; [self->iconWidth release]; [self->template release]; - [self->matrix release]; [super dealloc]; } @@ -345,6 +339,8 @@ NSString *WETreeView_Space = @"WETreeView_Space"; return ([a count] > 0) ? a : nil; } +/* handle requests */ + - (void)_takeValuesFromRequest:(WORequest *)_req inContext:(WOContext *)_ctx withArray:(NSArray *)array @@ -471,8 +467,11 @@ NSString *WETreeView_Space = @"WETreeView_Space"; return result; } +/* collect rows */ + - (void)appendList:(NSArray *)_list treeElement:(_WETreeMatrixElement *)_element + toTableRows:(NSMutableArray *)_matrix inContext:(WOContext *)_ctx { /* TODO: split up this method! */ @@ -498,8 +497,10 @@ NSString *WETreeView_Space = @"WETreeView_Space"; #endif for (i = 0; i < cnt; i++) { - id object = [_list objectAtIndex:i]; + id object; + object = [_list objectAtIndex:i]; + [_element setIndex:i]; [_element setItem:object]; @@ -601,7 +602,7 @@ NSString *WETreeView_Space = @"WETreeView_Space"; newElement = [[_WETreeMatrixElement alloc] initWithElement:_element]; - [self->matrix addObject:newElement]; + [_matrix addObject:newElement]; [newElement release]; newElement = nil; if (isZoom) { @@ -611,7 +612,8 @@ NSString *WETreeView_Space = @"WETreeView_Space"; newElement = [[_WETreeMatrixElement alloc] initWithElement:_element]; - [self appendList:sl treeElement:newElement inContext:_ctx]; + [self appendList:sl treeElement:newElement + toTableRows:_matrix inContext:_ctx]; [newElement release]; newElement = nil; } } @@ -626,50 +628,59 @@ NSString *WETreeView_Space = @"WETreeView_Space"; [newElement setLeaf:WETreeView_Leaf]; - [self->matrix addObject:newElement]; + [_matrix addObject:newElement]; [newElement release]; newElement = nil; } } } } -- (void)_calcMatrixInContext:(WOContext *)_ctx depth:(int *)_depth { - _WETreeMatrixElement *treeElm = nil; - NSArray *top = nil; +- (NSArray *)_calcMatrixInContext:(WOContext *)_ctx depth:(int *)_depth { + /* + Note: returns a retained object! + + This is the main entry for the calculation of the rows and the depth + nesting. + The rows are stored in _WETreeMatrixElement objects which know about + their colspan, depth and columns. + */ + NSMutableArray *tableRows; + _WETreeMatrixElement *treeElm; + NSArray *top; int i, cnt, d, maxDepth = 0; - top = [self->list valueInComponent:[_ctx component]]; + top = [self->list valueInComponent:[_ctx component]]; + tableRows = [[NSMutableArray alloc] initWithCapacity:64]; - [self->matrix release]; self->matrix = nil; - self->matrix = [[NSMutableArray allocWithZone:[self zone]] - initWithCapacity:64]; - treeElm = [[_WETreeMatrixElement alloc] init]; + [self appendList:top treeElement:treeElm toTableRows:tableRows + inContext:_ctx]; + [treeElm release]; treeElm = nil; - [self appendList:top treeElement:treeElm inContext:_ctx]; + cnt = [tableRows count]; - [treeElm release]; treeElm = nil; - - cnt = [self->matrix count]; - /* calc max depth */ for (i = 0; i < cnt; i++) { - d = [[self->matrix objectAtIndex:i] depth]; + d = [[tableRows objectAtIndex:i] depth]; maxDepth = (maxDepth < d) ? d : maxDepth; } - /* update depth */ + /* update colspan (max-depth minus element-depth) */ for (i = 0; i < cnt; i++) { _WETreeMatrixElement *element; - element = [self->matrix objectAtIndex:i]; - [element setColspan:maxDepth-[element depth]+1]; + element = [tableRows objectAtIndex:i]; + [element setColspan:(maxDepth - [element depth] + 1)]; } *_depth = maxDepth + 2; + return tableRows; } +/* generate response, main entry function */ + - (void)appendToResponse:(WOResponse *)_response inContext:(WOContext *)_ctx { WOComponent *comp; + NSArray *matrix; BOOL doTable; int i, cnt, depth; @@ -695,7 +706,7 @@ NSString *WETreeView_Space = @"WETreeView_Space"; @"otherTagString) { + if (self->otherTagString != nil) { [_response appendContentCharacter:' ']; [_response appendContentString: [self->otherTagString stringValueInComponent: @@ -703,10 +714,10 @@ NSString *WETreeView_Space = @"WETreeView_Space"; } [_response appendContentCharacter:'>']; } + + matrix = [self _calcMatrixInContext:_ctx depth:&depth]; - [self _calcMatrixInContext:_ctx depth:&depth]; - - /* append table title */ + /* append table title */ if (doTable) [_response appendContentString:@""]; @@ -722,34 +733,42 @@ NSString *WETreeView_Space = @"WETreeView_Space"; [_response appendContentString:@"
"]; else [_response appendContentString:@"
"]; + + /* generate content rows */ - cnt = [self->matrix count]; - - for (i = 0; i < cnt; i++) { + for (i = 0, cnt = [matrix count]; i < cnt; i++) { _WETreeMatrixElement *element; - element = [self->matrix objectAtIndex:i]; + element = [matrix objectAtIndex:i]; + + /* push positioning info into component */ if ([self->index isValueSettable]) - [self->index setUnsignedIntValue:[element index] - inComponent:comp]; - + [self->index setUnsignedIntValue:[element index] inComponent:comp]; + if ([self->item isValueSettable]) - [self->item setValue:[element item] - inComponent:comp]; + [self->item setValue:[element item] inComponent:comp]; if ([self->currentPath isValueSettable]) - [self->currentPath setValue:[element currentPath] - inComponent:comp]; + [self->currentPath setValue:[element currentPath] inComponent:comp]; + /* set active tree element in context (tree cannot be nested!) */ + [_ctx setObject:element forKey:WETreeView_TreeElement]; + /* start table row and update element-ids */ + [_ctx appendElementIDComponent:[element elementID]]; - [_ctx appendElementIDComponent:@"end"]; if (doTable) [_response appendContentString:@""]; + + /* generate content */ + [self->template appendToResponse:_response inContext:_ctx]; + + /* close table row and update element-ids */ + if (doTable) [_response appendContentString:@""]; else if (_ctx->wcFlags.xmlStyleEmptyElements) @@ -765,10 +784,12 @@ NSString *WETreeView_Space = @"WETreeView_Space"; if (doTable) [_response appendContentString:@"
"]; + + /* cleanup rendering context */ [self removeConfigInContext:_ctx]; [_ctx removeObjectForKey:WETreeView_RenderNoTable]; - [self->matrix release]; self->matrix = nil; + [matrix release]; matrix = nil; } @end /* WETreeView */