]> err.no Git - sope/commitdiff
treeview refactoring
authorhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Mon, 1 Aug 2005 12:13:13 +0000 (12:13 +0000)
committerhelge <helge@e4a50df8-12e2-0310-a44c-efbce7f8a7e3>
Mon, 1 Aug 2005 12:13:13 +0000 (12:13 +0000)
git-svn-id: http://svn.opengroupware.org/SOPE/trunk@954 e4a50df8-12e2-0310-a44c-efbce7f8a7e3

sope-appserver/WEExtensions/ChangeLog
sope-appserver/WEExtensions/JSStringTable.m
sope-appserver/WEExtensions/Version
sope-appserver/WEExtensions/WETreeData.m
sope-appserver/WEExtensions/WETreeMatrixElement.h
sope-appserver/WEExtensions/WETreeMatrixElement.m
sope-appserver/WEExtensions/WETreeView.m

index b8fa5897d8fccad844978e52c013cbfe8a871d21..2080e5e05a501221e1085bb13a5761e294ddd377 100644 (file)
@@ -1,3 +1,11 @@
+2005-08-01  Helge Hess  <helge.hess@skyrix.com>
+
+       * v4.5.79
+
+       * WETreeView.m: major code cleanups
+
+       * WETreeMatrixElement.m: minor performance improvements
+
 2005-07-22  Marcus Mueller  <znek@mulle-kybernetik.com>
 
        * JSStringTable.m: if 'if-none-match' is not set, do not return a 304
index ef8bfa62392b74fba1c9ba5c51a0a952a4def091..d62815ff76757db7ebbac4c4edae8024de025fa5 100644 (file)
     if (isFirst) isFirst = NO;
     else [_response appendContentString:@",\n"];
     
-    value = [_table objectForKey:key];
+    value = [(NSDictionary *)_table objectForKey:key];
     
     /* escape value */
     value = [value stringByReplacingString:@"\"" withString:@"\\\""];
index 847ef478dbd54916006052d7714b56409143c967..df461f3de67a7956942a5fa3e338d4f2d733d3c8 100644 (file)
@@ -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
index 100a3c4c160deacc4f6fd40123949e79f0ff6fdf..572e1b76e7c0f39e1eb89eb0b4d97b427e88392a 100644 (file)
@@ -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:@"</nobr></td>"];
 }
 
+- (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:@"<td"];
+      [self appendExtraAttributesToResponse:_response inContext:_ctx];
+      [_response appendContentString:@" valign=\"middle\" align=\"center\""];
+        
+      if (iconWidth) {
+        NSString *s;
+        s = [[StrClass alloc] initWithFormat:@" width=\"%@\"", iconWidth];
+        [_response appendContentString:s];
+        [s release];
+      }
+        
+      if (treeElm == WETreeView_Plus     || treeElm == WETreeView_Minus ||
+          treeElm == WETreeView_Junction || treeElm == WETreeView_Line) {
+        NSString *img;
+          
+        img = [_ctx objectForKey:WETreeView_Line];
+        img = WEUriOfResource(img, _ctx);
+        if (img) {
+          [_response appendContentString:@" background=\""];
+          [_response appendContentString:img];
+          [_response appendContentCharacter:'"'];
+        }
+      }
+      [_response appendContentString:@"><nobr>"];
+    }
+    
+    /* this appends plus and minus images and links to expand/collapse */
+    [self _appendTreeElement:treeElm toResponse:_response inContext:_ctx];
+    
+    if (self->doTable)
+      [_response appendContentString:@"</nobr></td>"];
+  }
+}
+
 - (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:@"<td"];
-        [self appendExtraAttributesToResponse:_response inContext:_ctx];
-        [_response appendContentString:@" valign=\"middle\" align=\"center\""];
-        
-        if (iconWidth) {
-          NSString *s;
-          s = [[StrClass alloc] initWithFormat:@" width=\"%@\"", iconWidth];
-          [_response appendContentString:s];
-          [s release];
-        }
-        
-        if (treeElm == WETreeView_Plus     || treeElm == WETreeView_Minus ||
-            treeElm == WETreeView_Junction || treeElm == WETreeView_Line) {
-          NSString *img;
-          
-          img = [_ctx objectForKey:WETreeView_Line];
-          img = WEUriOfResource(img, _ctx);
-          if (img) {
-            [_response appendContentString:@" background=\""];
-            [_response appendContentString:img];
-            [_response appendContentCharacter:'"'];
-          }
-        }
-        [_response appendContentString:@"><nobr>"];
-      }
-        
-      [self _appendTreeElement:treeElm toResponse:_response inContext:_ctx];
-      if (self->doTable)
-        [_response appendContentString:@"</nobr></td>"];
-    }
+    /* 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:@"<td"];
@@ -362,6 +380,7 @@ static Class StrClass = Nil;
       [_response appendContentString:@"</td>"];
   }
   else { // ! isTree
+    /* this is a follow-up cell in a row, it renders just the content */
     if (self->doTable) {
       [_response appendContentString:@"<td"];
       [self appendExtraAttributesToResponse:_response inContext:_ctx];
@@ -376,13 +395,15 @@ static Class StrClass = Nil;
     
     /* add cell content */
     [self->template appendToResponse:_response inContext:_ctx];
-    if (content) [_response appendContentHTMLString:content];
+    if (content != nil) [_response appendContentHTMLString:content];
 
     if (self->doTable)
       [_response appendContentString:@"</td>"];
   }
 }
 
+/* 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];
index b8bccda834439a4c257cbe2f86af08e1e99d0e35..99faf9b3fd1aae83c25c20d1272b18e395538764 100644 (file)
 
 #import <Foundation/NSString.h>
 
-#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
 {
index d4170c0a76071dff8fa35b0998a1ccc2c4817e0c..841381592b78b6e8250a280f92fcf65114c9c2a4 100644 (file)
@@ -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];
   }
index fe4a156dc0c9d87d642b8cdab50d289ae382168a..f0b6e3ad4380b22439daeeda76eb499f5088be6c 100644 (file)
 
 #include <NGObjWeb/WODynamicElement.h>
 
-@class NSMutableArray;
-
 @interface WETreeView : WODynamicElement
 {
   // WODynamicElement: extraAttributes
   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";
                @"<table border='0' cellspacing='0' cellpadding='0'"];
 
     [self appendExtraAttributesToResponse:_response inContext:_ctx];
-    if (self->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:@"<tr>"];
 
@@ -722,34 +733,42 @@ NSString *WETreeView_Space          = @"WETreeView_Space";
     [_response appendContentString:@"<br />"];
   else
     [_response appendContentString:@"<br>"];
+  
+  /* 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:@"<tr>"];
+    
+    /* generate content */
+    
     [self->template appendToResponse:_response inContext:_ctx];
+
+    /* close table row and update element-ids */
+    
     if (doTable)
       [_response appendContentString:@"</tr>"];
     else if (_ctx->wcFlags.xmlStyleEmptyElements)
@@ -765,10 +784,12 @@ NSString *WETreeView_Space          = @"WETreeView_Space";
 
   if (doTable)
     [_response appendContentString:@"</table>"];
+  
+  /* cleanup rendering context */
 
   [self removeConfigInContext:_ctx];
   [_ctx removeObjectForKey:WETreeView_RenderNoTable];
-  [self->matrix release]; self->matrix = nil;
+  [matrix release]; matrix = nil;
 }
 
 @end /* WETreeView */