From f9fbfb4a040477a11c6ca909e3e54c1d23adc1a5 Mon Sep 17 00:00:00 2001 From: helge Date: Mon, 14 Feb 2005 15:06:16 +0000 Subject: [PATCH] fixed handling of root nodes in mailtree git-svn-id: http://svn.opengroupware.org/SOGo/trunk@556 d1b88da0-ebda-0310-925b-ed51d893ca5b --- SOGo/UI/Mailer/ChangeLog | 12 +++ SOGo/UI/Mailer/README | 6 ++ SOGo/UI/Mailer/UIxMailMainFrame.m | 16 ++++ SOGo/UI/Mailer/UIxMailMainFrame.wox | 3 +- SOGo/UI/Mailer/UIxMailTree.m | 114 +++++++++++++++++++++------- SOGo/UI/Mailer/UIxMailTreeBlock.h | 13 ++++ SOGo/UI/Mailer/UIxMailTreeBlock.m | 48 ++++++++++++ SOGo/UI/Mailer/Version | 2 +- SOGo/UI/Mailer/mailer.css | 3 +- 9 files changed, 188 insertions(+), 29 deletions(-) diff --git a/SOGo/UI/Mailer/ChangeLog b/SOGo/UI/Mailer/ChangeLog index 2015c3fa..c995e1b7 100644 --- a/SOGo/UI/Mailer/ChangeLog +++ b/SOGo/UI/Mailer/ChangeLog @@ -1,3 +1,15 @@ +2005-02-14 Helge Hess + + * v0.9.105 + + * UIxMailTree.m: fixed handling of root nodes (properly display all + children of the root node) + + * UIxMailTreeBlock.m: generate a description + + * UIxMailMainFrame.m, UIxMailTree.m: made root class of tree + configurable using 'SOGoMailTreeRootClass' default + 2005-02-13 Helge Hess * mailer.css: added left-padding to treecell to make it look better diff --git a/SOGo/UI/Mailer/README b/SOGo/UI/Mailer/README index 7f893ff0..60b6beb3 100644 --- a/SOGo/UI/Mailer/README +++ b/SOGo/UI/Mailer/README @@ -42,6 +42,12 @@ SOGoMailEditorKeepTmpFile - for debugging, if a mail was send, keep the file containing the MIME in the temporary directory for review instead of deleting it +SOGoMailTreeRootClass +- configure the root class of the mail tree, eg: + - SOGoMailAccounts - standard view, show all IMAP4 accounts + - SOGoMailAccount - just show the standard mail account (tree at Inbox!) + - SoApplication - stop at the application object (show all folders) + Notes ===== diff --git a/SOGo/UI/Mailer/UIxMailMainFrame.m b/SOGo/UI/Mailer/UIxMailMainFrame.m index 1c7c006b..8bc55ebe 100644 --- a/SOGo/UI/Mailer/UIxMailMainFrame.m +++ b/SOGo/UI/Mailer/UIxMailMainFrame.m @@ -41,6 +41,18 @@ @implementation UIxMailMainFrame +static NSString *treeRootClassName = nil; + ++ (void)initialize { + NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; + + treeRootClassName = [[ud stringForKey:@"SOGoMailTreeRootClass"] copy]; + if (treeRootClassName) + NSLog(@"Note: use class '%@' as root for mail tree.", treeRootClassName); + else + treeRootClassName = @"SOGoMailAccounts"; +} + - (void)dealloc { [self->item release]; [self->title release]; @@ -51,6 +63,10 @@ /* accessors */ +- (NSString *)treeRootClassName { + return treeRootClassName; +} + - (void)setHideFolderTree:(BOOL)_flag { self->hideFolderTree = _flag; } diff --git a/SOGo/UI/Mailer/UIxMailMainFrame.wox b/SOGo/UI/Mailer/UIxMailMainFrame.wox index 71760e4d..1e6679a6 100644 --- a/SOGo/UI/Mailer/UIxMailMainFrame.wox +++ b/SOGo/UI/Mailer/UIxMailMainFrame.wox @@ -63,7 +63,8 @@
- +
diff --git a/SOGo/UI/Mailer/UIxMailTree.m b/SOGo/UI/Mailer/UIxMailTree.m index 5284b414..832308fc 100644 --- a/SOGo/UI/Mailer/UIxMailTree.m +++ b/SOGo/UI/Mailer/UIxMailTree.m @@ -23,6 +23,7 @@ @interface UIxMailTree : UIxComponent { + NSString *rootClassName; id rootNodes; id item; } @@ -46,7 +47,14 @@ @implementation UIxMailTree +static BOOL debugBlocks = NO; + ++ (void)initialize { + [UIxMailTreeBlock class]; // ensure that globals are initialized +} + - (void)dealloc { + [self->rootClassName release]; [self->rootNodes release]; [self->item release]; [super dealloc]; @@ -69,6 +77,13 @@ /* accessors */ +- (void)setRootClassName:(id)_rootClassName { + ASSIGNCOPY(self->rootClassName, _rootClassName); +} +- (id)rootClassName { + return self->rootClassName; +} + - (void)setItem:(id)_item { ASSIGN(self->item, _item); } @@ -92,8 +107,15 @@ NSArray *names; unsigned i, count; - if ((names = [_object toManyRelationshipKeys]) == nil) + if ((names = [_object toManyRelationshipKeys]) == nil) { + [self logWithFormat:@"no to-many: %@", _object]; return nil; + } + + if (debugBlocks) { + [self logWithFormat:@"to-many: %@ %@", _object, + [names componentsJoinedByString:@","]]; + } count = [names count]; ma = [NSMutableArray arrayWithCapacity:(count + 1)]; @@ -121,8 +143,7 @@ return YES; } - // TODO: make this a parameter to make UIxMailTree reusable - return [_object isKindOfClass:NSClassFromString(@"SOGoMailAccounts")]; + return [_object isKindOfClass:NSClassFromString([self rootClassName])]; } - (NSString *)treeNavigationLinkForObject:(id)_object atDepth:(int)_depth { @@ -194,9 +215,9 @@ we do not generate blocks for folders which are not displayed anyway. */ blocks = [[_o toManyRelationshipKeys] count] > 0 - ? [[NSArray alloc] initWithObjects:@"FAKE", nil] + ? UIxMailTreeHasChildrenMarker : nil; - + [self getTitle:&n andIcon:&i forObject:_o]; md = [UIxMailTreeBlock blockWithName:nil @@ -217,6 +238,11 @@ NSArray *folders; NSString *title, *icon; unsigned i, count; + + if (debugBlocks) { + [self logWithFormat:@"block for root node 0x%08X<%@>", + _object, NSStringFromClass([_object class])]; + } /* process child folders */ @@ -255,12 +281,18 @@ NSArray *folders; NSString *title, *icon; unsigned i, count; - + // TODO: maybe we can join the two implementations, this might not be // necessary if ([self isRootObject:_object]) /* we are at the top */ return [self treeNavigationBlockForRootNode:_object]; + if (debugBlocks) { + [self logWithFormat:@"block for active node 0x%08X<%@> - %@", + _object, NSStringFromClass([_object class]), + [_object davDisplayName]]; + } + /* process child folders */ folders = [self fetchSubfoldersOfObject:_object]; @@ -290,18 +322,18 @@ withActiveChildBlock:(UIxMailTreeBlock *)_activeChildBlock depth:(int)_depth { - UIxMailTreeBlock *md; + /* + Note: 'activeChildBlock' here doesn't mean that the block is the selected + folder in the tree. Its just the element which is active in the + list of subfolders. + */ + UIxMailTreeBlock *resultBlock; NSMutableArray *blocks; NSString *activeName; NSArray *folders; NSString *title, *icon; unsigned i, count; - if ([self isRootObject:_object]) /* we are at the top */ - return _activeChildBlock; - - /* the following is not run on the OGoMailAccounts (root) object */ - activeName = [_activeChildBlock valueForKey:@"name"]; /* process child folders */ @@ -325,45 +357,75 @@ /* build block */ [self getTitle:&title andIcon:&icon forObject:_object]; - md = [UIxMailTreeBlock blockWithName:[_object nameInContainer] - title:title iconName:icon - link:[self treeNavigationLinkForObject:_object - atDepth:(_depth + 1)] - isPathNode:YES isActiveNode:NO - childBlocks:blocks]; + resultBlock = [UIxMailTreeBlock blockWithName:[_object nameInContainer] + title:title iconName:icon + link: + [self treeNavigationLinkForObject:_object + atDepth:(_depth + 1)] + isPathNode:YES isActiveNode:NO + childBlocks:blocks]; - /* recurse up */ + /* recurse up unless we are at the root */ + + if ([self isRootObject:_object]) /* we are at the top */ + return resultBlock; return [self treeNavigationBlockForObject:[_object container] - withActiveChildBlock:md + withActiveChildBlock:resultBlock depth:(_depth + 1)]; } -- (id)buildNavigationNodesForObject:(id)_object { - id block; +- (UIxMailTreeBlock *)buildNavigationNodesForObject:(id)_object { + /* + This is the top-level 'flattening' method. The _object is the active + object in the tree, that is, usually a "current folder". + + The tree will show: + all subfolders of the current folder, + all parent folders of the current folder up to some root, + all siblings along the parent chain. + */ + UIxMailTreeBlock *block; + /* + This is the cursor, we create nodes below that for direct subfolders + */ + if (debugBlocks) [self logWithFormat:@"ACTIVE block ..."]; block = [self treeNavigationBlockForActiveNode:_object]; + if (debugBlocks) [self logWithFormat:@" ACTIVE block: %@", block]; - if ([self isRootObject:_object]) + if ([self isRootObject:_object]) { + if (debugBlocks) [self logWithFormat:@" active block is root."]; return block; + } - /* the following returns the root block! */ + /* + The following returns the root block. It calculates the chain up to the + root folder starting with the parent of the current object. + */ + if (debugBlocks) [self logWithFormat:@"ACTIVE parent block ..."]; block = [self treeNavigationBlockForObject:[_object container] withActiveChildBlock:block depth:1]; + if (debugBlocks) [self logWithFormat:@"done: %@", block]; return block; } /* tree */ - (NSArray *)rootNodes { - id navNode; + UIxMailTreeBlock *navNode; if (self->rootNodes != nil) return self->rootNodes; navNode = [self buildNavigationNodesForObject:[self clientObject]]; - self->rootNodes = [[NSArray alloc] initWithObjects:&navNode count:1]; + + if ([navNode hasChildren] && [navNode areChildrenLoaded]) + self->rootNodes = [[navNode children] retain]; + else if (navNode) + self->rootNodes = [[NSArray alloc] initWithObjects:&navNode count:1]; + return self->rootNodes; } diff --git a/SOGo/UI/Mailer/UIxMailTreeBlock.h b/SOGo/UI/Mailer/UIxMailTreeBlock.h index ee95f3e4..cc3b3169 100644 --- a/SOGo/UI/Mailer/UIxMailTreeBlock.h +++ b/SOGo/UI/Mailer/UIxMailTreeBlock.h @@ -19,6 +19,9 @@ 02111-1307, USA. */ +#ifndef __UIxMailTreeBlock_H__ +#define __UIxMailTreeBlock_H__ + #import @class NSString, NSArray; @@ -29,6 +32,8 @@ A helper object for UIxMailTree. */ +extern id UIxMailTreeHasChildrenMarker; + @interface UIxMailTreeBlock : NSObject { NSString *name; @@ -51,4 +56,12 @@ link:(NSString *)_link isPathNode:(BOOL)_isPath isActiveNode:(BOOL)_isActive childBlocks:(NSArray *)_blocks; +/* accessors */ + +- (BOOL)hasChildren; +- (BOOL)areChildrenLoaded; +- (NSArray *)children; + @end + +#endif /* __UIxMailTreeBlock_H__ */ diff --git a/SOGo/UI/Mailer/UIxMailTreeBlock.m b/SOGo/UI/Mailer/UIxMailTreeBlock.m index 39309870..257631e4 100644 --- a/SOGo/UI/Mailer/UIxMailTreeBlock.m +++ b/SOGo/UI/Mailer/UIxMailTreeBlock.m @@ -24,6 +24,15 @@ @implementation UIxMailTreeBlock +id UIxMailTreeHasChildrenMarker = nil; + ++ (void)initialize { + // TODO: needs to be an array because the WETreeView requires a + // children array + UIxMailTreeHasChildrenMarker = + [[NSArray alloc] initWithObjects:@"FAKE", nil]; +} + + (id)blockWithName:(NSString *)_name title:(NSString *)_title iconName:(NSString *)_icon link:(NSString *)_link isPathNode:(BOOL)_isPath isActiveNode:(BOOL)_isActive @@ -80,7 +89,21 @@ return self->iconName; } +- (BOOL)hasChildren { + if (self->blocks == UIxMailTreeHasChildrenMarker) + return YES; + return [self->blocks count] > 0 ? YES : NO; +} + +- (BOOL)areChildrenLoaded { + return self->blocks != UIxMailTreeHasChildrenMarker ? YES : NO; +} + - (NSArray *)children { + if (self->blocks == UIxMailTreeHasChildrenMarker) + // TODO: print a warning + return self->blocks; + return self->blocks; } @@ -91,4 +114,29 @@ return self->flags.isActive ? YES : NO; } +/* description */ + +- (void)appendAttributesToDescription:(NSMutableString *)_ms { + if (self->name != nil) [_ms appendFormat:@" name='%@'", self->name]; + if (self->title != nil) [_ms appendFormat:@" title='%@'", self->title]; + + if ([self isPathNode]) [_ms appendString:@" path"]; + if ([self isActiveNode]) [_ms appendString:@" active"]; + + if (self->blocks == UIxMailTreeHasChildrenMarker) + [_ms appendString:@" has-children"]; + else if ([self->blocks count] > 0) + [_ms appendFormat:@" children=%@", self->blocks]; +} + +- (NSString *)description { + NSMutableString *ms; + + ms = [NSMutableString stringWithCapacity:64]; + [ms appendFormat:@"<0x%08X[%@]:", self, NSStringFromClass([self class])]; + [self appendAttributesToDescription:ms]; + [ms appendString:@">"]; + return ms; +} + @end /* UIxMailTreeBlock */ diff --git a/SOGo/UI/Mailer/Version b/SOGo/UI/Mailer/Version index 73f8394a..8991b9b6 100644 --- a/SOGo/UI/Mailer/Version +++ b/SOGo/UI/Mailer/Version @@ -1,6 +1,6 @@ # version file -SUBMINOR_VERSION:=104 +SUBMINOR_VERSION:=105 # v0.9.100 requires libNGMime v4.5.213 # v0.9.99 requires libNGMime v4.5.212 diff --git a/SOGo/UI/Mailer/mailer.css b/SOGo/UI/Mailer/mailer.css index 090d781e..74c06af5 100644 --- a/SOGo/UI/Mailer/mailer.css +++ b/SOGo/UI/Mailer/mailer.css @@ -90,7 +90,8 @@ font-size: 10pt; color: black; vertical-align: bottom; - padding-left: 4px; + padding-left: 4px; /* move away from the icon */ + padding-right: 2px; /* move away from the right border */ white-space: nowrap; } -- 2.39.5