02111-1307, USA.
*/
-#include <SOGoUI/UIxComponent.h>
+#import "common.h"
-@interface UIxMailTree : UIxComponent
-{
- NSString *rootClassName;
- NSString *treeFolderAction;
- id rootNodes;
- id item;
-}
-@end
+#import <SoObjects/Mailer/SOGoMailBaseObject.h>
+#import <SoObjects/Mailer/SOGoMailAccount.h>
+#import <SoObjects/Mailer/SOGoMailFolder.h>
+#import <NGObjWeb/SoComponent.h>
+#import <NGObjWeb/SoObject+SoDAV.h>
-#include "UIxMailTreeBlock.h"
-#include <SoObjects/Mailer/SOGoMailBaseObject.h>
-#include <SoObjects/Mailer/SOGoMailAccount.h>
-#include "common.h"
-#include <NGObjWeb/SoComponent.h>
-#include <NGObjWeb/SoObject+SoDAV.h>
+#import "UIxMailTree.h"
+#import "UIxMailTreeBlock.h"
/*
Support special icons:
static BOOL debugBlocks = NO;
-+ (void)initialize {
++ (void)initialize
+{
[UIxMailTreeBlock class]; // ensure that globals are initialized
}
-- (void)dealloc {
- [self->treeFolderAction release];
- [self->rootClassName release];
- [self->rootNodes release];
- [self->item release];
+- (id) init
+{
+ if ((self = [super init]))
+ {
+ flattenedNodes = nil;
+ }
+
+ return self;
+}
+
+- (void) dealloc
+{
+ [treeFolderAction release];
+ [rootClassName release];
+ [rootNodes release];
+ [item release];
+ [flattenedNodes release];
[super dealloc];
}
/* icons */
-- (NSString *)defaultIconName {
+- (NSString *) defaultIconName
+{
return @"tbtv_leaf_corner_17x17.gif";
}
/* accessors */
- (void)setRootClassName:(id)_rootClassName {
- ASSIGNCOPY(self->rootClassName, _rootClassName);
+ ASSIGNCOPY(rootClassName, _rootClassName);
}
- (id)rootClassName {
- return self->rootClassName;
+ return rootClassName;
}
- (void)setItem:(id)_item {
- ASSIGN(self->item, _item);
+ ASSIGN(item, _item);
}
- (id)item {
- return self->item;
+ return item;
}
- (void)setTreeFolderAction:(NSString *)_action {
- ASSIGNCOPY(self->treeFolderAction, _action);
+ ASSIGNCOPY(treeFolderAction, _action);
}
- (NSString *)treeFolderAction {
- return self->treeFolderAction;
+ return treeFolderAction;
}
- (NSString *)itemIconName {
[self logWithFormat:@"to-many: %@ %@", _object,
[names componentsJoinedByString:@","]];
}
-
+
count = [names count];
ma = [NSMutableArray arrayWithCapacity:(count + 1)];
for (i = 0; i < count; i++) {
return [_object isKindOfClass:NSClassFromString([self rootClassName])];
}
-- (NSString *)treeNavigationLinkForObject:(id)_object atDepth:(int)_depth {
- NSString *link;
- unsigned i;
-
- link = [[_object nameInContainer] stringByAppendingString:@"/"];
- link = [link stringByAppendingString:[self treeFolderAction]];
-
- switch (_depth) {
- case 0: return link;
- case 1: return [@"../" stringByAppendingString:link];
- case 2: return [@"../../" stringByAppendingString:link];
- case 3: return [@"../../../" stringByAppendingString:link];
- }
+- (NSString *)treeNavigationLinkForObject:(id)_object
+ atDepth:(int)_depth
+{
+ NSMutableString *link;
+ int i;
+ link = [NSMutableString new];
+ [link autorelease];
+
for (i = 0; i < _depth; i++)
- link = [@"../" stringByAppendingString:link];
+ [link appendString: @"../"];
+
+ [link appendFormat: @"%@/%@",
+ [_object nameInContainer],
+ [self treeFolderAction]];
+
return link;
}
-- (void)getTitle:(NSString **)_t andIcon:(NSString **)_icon
- forObject:(id)_object
+- (void) getTitle: (NSString **)_t
+ folderType: (NSString **)_ft
+ andIcon: (NSString **)_icon
+ forObject: (id)_object
{
// TODO: need to refactor for reuse!
NSString *ftype;
unsigned len;
+
+// if ([_object respondsToSelector: @selector (outlookFolderClass)])
+// ftype = [_object outlookFolderClass];
+// else
+ ftype = [_object valueForKey:@"outlookFolderClass"];
+ len = [ftype length];
- ftype = [_object valueForKey:@"outlookFolderClass"];
- len = [ftype length];
-
+ *_ft = nil;
+
switch (len) {
case 8:
if ([ftype isEqualToString:@"IPF.Sent"]) {
*_t = [self labelForKey:@"SentFolderName"];
*_icon = @"tbtv_sent_17x17.gif";
+ *_ft = @"sent";
return;
}
break;
if ([ftype isEqualToString:@"IPF.Inbox"]) {
*_t = [self labelForKey:@"InboxFolderName"];
*_icon = @"tbtv_inbox_17x17.gif";
+ *_ft = @"inbox";
return;
}
if ([ftype isEqualToString:@"IPF.Trash"]) {
*_t = [self labelForKey:@"TrashFolderName"];
*_icon = @"tbtv_trash_17x17.gif";
+ *_ft = @"trash";
return;
}
break;
if ([ftype isEqualToString:@"IPF.Drafts"]) {
*_t = [self labelForKey:@"DraftsFolderName"];
*_icon = @"tbtv_drafts_17x17.gif";
+ *_ft = @"drafts";
return;
}
- if ([ftype isEqualToString:@"IPF.Filter"]) {
- *_t = [self labelForKey:@"SieveFolderName"];
- *_icon = nil;
- return;
- }
+// if ([ftype isEqualToString:@"IPF.Filter"]) {
+// *_t = [self labelForKey:@"SieveFolderName"];
+// *_icon = nil;
+// *_ft = @"sieve";
+// return;
+// }
break;
}
-
+
*_t = [_object davDisplayName];
*_icon = nil;
if ([_object isKindOfClass:NSClassFromString(@"SOGoMailFolder")])
*_icon = nil;
else if ([_object isKindOfClass:NSClassFromString(@"SOGoMailAccount")]) {
- *_icon = @"tbtv_inbox_17x17.gif";
+ *_icon = @"tbtv_account_17x17.gif";
+
+ *_ft = @"account";
/* title processing is somehow Agenor specific and should be done in UI */
*_t = [[_object nameInContainer] titleForSOGoIMAP4String];
}
else if ([_object isKindOfClass:NSClassFromString(@"SOGoMailAccounts")])
- *_icon = @"tbtv_inbox_17x17.gif";
+ *_icon = @"tbtv_account_17x17.gif";
else if ([_object isKindOfClass:NSClassFromString(@"SOGoUserFolder")])
*_icon = @"tbtv_inbox_17x17.gif";
else {
// TODO: use drafts icon for other SOGo folders
*_icon = @"tbtv_drafts_17x17.gif";
}
-
- return;
}
-- (UIxMailTreeBlock *)treeNavigationBlockForLeafNode:(id)_o atDepth:(int)_d {
+- (UIxMailTreeBlock *) treeNavigationBlockForLeafNode: (id) _o
+ atDepth: (int) _d
+{
UIxMailTreeBlock *md;
- NSString *n, *i;
+ NSString *n, *i, *ft;
id blocks;
-
+
/*
Trigger plus in treeview if it has subfolders. It is an optimization that
we do not generate blocks for folders which are not displayed anyway.
blocks = [[_o toManyRelationshipKeys] count] > 0
? UIxMailTreeHasChildrenMarker
: nil;
-
- [self getTitle:&n andIcon:&i forObject:_o];
-
- md = [UIxMailTreeBlock blockWithName:nil
- title:n iconName:i
- link:[self treeNavigationLinkForObject:_o atDepth:_d]
- isPathNode:NO isActiveNode:NO
- childBlocks:blocks];
+
+ [self getTitle: &n folderType: &ft andIcon: &i forObject:_o];
+
+ md = [UIxMailTreeBlock blockWithName: nil
+ title: n
+ iconName: i
+ link: [self treeNavigationLinkForObject:_o atDepth:_d]
+ isPathNode:NO
+ isActiveNode:NO
+ childBlocks: blocks];
return md;
}
UIxMailTreeBlock *md;
NSMutableArray *blocks;
NSArray *folders;
- NSString *title, *icon;
+ NSString *title, *icon, *ft;
unsigned i, count;
if (debugBlocks) {
for (i = 0; i < count; i++) {
id block;
- block = [self treeNavigationBlockForLeafNode:[folders objectAtIndex:i]
+ block = [self treeNavigationBlockForLeafNode: [folders objectAtIndex:i]
atDepth:0];
if ([block isNotNull]) [blocks addObject:block];
}
/* build block */
- [self getTitle:&title andIcon:&icon forObject:_object];
- md = [UIxMailTreeBlock blockWithName:[_object nameInContainer]
- title:title iconName:icon
- link:[@"../" stringByAppendingString:
- [_object nameInContainer]]
- isPathNode:YES isActiveNode:YES
- childBlocks:blocks];
+ [self getTitle:&title folderType: &ft andIcon:&icon forObject:_object];
+
+ md = [UIxMailTreeBlock blockWithName: [_object nameInContainer]
+ title: title
+ iconName: icon
+ link: [@"../" stringByAppendingString:
+ [_object nameInContainer]]
+ isPathNode: YES
+ isActiveNode: YES
+ childBlocks: blocks];
return md;
}
-- (UIxMailTreeBlock *)treeNavigationBlockForActiveNode:(id)_object {
+- (UIxMailTreeBlock *) fullTreeNavigationBlockForNode: (id)_object
+{
+ UIxMailTreeBlock *md;
+ NSMutableArray *blocks;
+ NSArray *folders;
+ NSString *title, *icon, *ft;
+ unsigned i, count;
+
+ if (debugBlocks)
+ [self logWithFormat:@"block for root node 0x%08X<%@>",
+ _object, NSStringFromClass([_object class])];
+
+ folders = [self fetchSubfoldersOfObject: _object];
+ count = [folders count];
+ blocks = [NSMutableArray arrayWithCapacity: count];
+ for (i = 0; i < count; i++)
+ {
+ id block;
+
+ block = [self fullTreeNavigationBlockForNode: [folders objectAtIndex:i]];
+ if ([block isNotNull]) [blocks addObject:block];
+ }
+
+ if (![blocks count])
+ blocks = nil;
+
+ [self getTitle: &title folderType: &ft andIcon: &icon forObject: _object];
+// NSLog (@"*********** title = '%@'/icon = '%@'", title, icon);
+
+ md = [UIxMailTreeBlock blockWithName: [_object nameInContainer]
+ title: title
+ iconName: icon
+ link: [@"../" stringByAppendingString:
+ [_object nameInContainer]]
+ isPathNode: YES
+ isActiveNode: YES
+ childBlocks: blocks];
+ [md setFolderType: ft];
+
+ return md;
+}
+
+- (UIxMailTreeBlock *) treeNavigationBlockForActiveNode: (id) _object
+{
/*
This generates the block for the clientObject (the object which has the
focus)
UIxMailTreeBlock *md;
NSMutableArray *blocks;
NSArray *folders;
- NSString *title, *icon;
+ NSString *title, *icon, *ft;
unsigned i, count;
// TODO: maybe we can join the two implementations, this might not be
for (i = 0; i < count; i++) {
UIxMailTreeBlock *block;
- block = [self treeNavigationBlockForLeafNode:[folders objectAtIndex:i]
- atDepth:0];
+ block = [self treeNavigationBlockForLeafNode: [folders objectAtIndex:i]
+ atDepth: 0];
if ([block isNotNull]) [blocks addObject:block];
}
if ([blocks count] == 0) blocks = nil;
-
+
/* build block */
- [self getTitle:&title andIcon:&icon forObject:_object];
- md = [UIxMailTreeBlock blockWithName:[_object nameInContainer]
- title:title iconName:icon
- link:@"."
- isPathNode:YES isActiveNode:YES
- childBlocks:blocks];
+ [self getTitle:&title folderType: &ft andIcon:&icon forObject:_object];
+ md = [UIxMailTreeBlock blockWithName: [_object nameInContainer]
+ title: title
+ iconName: icon
+ link: @"."
+ isPathNode: YES
+ isActiveNode: YES
+ childBlocks: blocks];
return md;
}
-- (UIxMailTreeBlock *)treeNavigationBlockForObject:(id)_object
- withActiveChildBlock:(UIxMailTreeBlock *)_activeChildBlock
- depth:(int)_depth
+- (UIxMailTreeBlock *)
+ treeNavigationBlockForObject: (id) _object
+ withActiveChildBlock: (UIxMailTreeBlock *) _activeChildBlock
+ depth: (int) _depth
{
/*
Note: 'activeChildBlock' here doesn't mean that the block is the selected
NSMutableArray *blocks;
NSString *activeName;
NSArray *folders;
- NSString *title, *icon;
+ NSString *title, *icon, *ft;
unsigned i, count;
activeName = [_activeChildBlock valueForKey:@"name"];
folder = [folders objectAtIndex:i];
block = [activeName isEqualToString:[folder nameInContainer]]
? _activeChildBlock
- : [self treeNavigationBlockForLeafNode:folder atDepth:_depth];
+ : [self treeNavigationBlockForLeafNode: folder
+ atDepth:_depth];
if ([block isNotNull]) [blocks addObject:block];
}
else
blocks = nil;
}
-
+
/* build block */
- [self getTitle:&title andIcon:&icon forObject:_object];
- resultBlock = [UIxMailTreeBlock blockWithName:[_object nameInContainer]
- title:title iconName:icon
- link:
- [self treeNavigationLinkForObject:_object
- atDepth:(_depth + 1)]
- isPathNode:YES isActiveNode:NO
- childBlocks:blocks];
+ [self getTitle:&title folderType: &ft andIcon:&icon forObject:_object];
+ resultBlock
+ = [UIxMailTreeBlock blockWithName: [_object nameInContainer]
+ title: title
+ iconName: icon
+ link:
+ [self treeNavigationLinkForObject: _object
+ atDepth: (_depth + 1)]
+ isPathNode:YES isActiveNode:NO
+ childBlocks:blocks];
/* recurse up unless we are at the root */
if (debugBlocks) [self logWithFormat:@"ACTIVE parent block ..."];
block = [self treeNavigationBlockForObject:[_object container]
withActiveChildBlock:block
- depth:1];
+ depth: 1];
if (debugBlocks) [self logWithFormat:@"done: %@", block];
return block;
}
- (NSArray *)rootNodes {
UIxMailTreeBlock *navNode;
- if (self->rootNodes != nil)
- return self->rootNodes;
+ if (rootNodes != nil)
+ return rootNodes;
navNode = [self buildNavigationNodesForObject:[self clientObject]];
if ([navNode hasChildren] && [navNode areChildrenLoaded])
- self->rootNodes = [[navNode children] retain];
+ rootNodes = [[navNode children] retain];
else if (navNode)
- self->rootNodes = [[NSArray alloc] initWithObjects:&navNode count:1];
+ rootNodes = [[NSArray alloc] initWithObjects:&navNode count:1];
- return self->rootNodes;
+ return rootNodes;
+}
+
+- (int) addNodes: (NSArray *) nodes
+ atSerial: (int) startSerial
+ forParent: (int) parent
+ withRootName: (NSString *) rootName
+ toArray: (NSMutableArray *) array
+{
+ unsigned int count, max, currentSerial;
+ UIxMailTreeBlock *curNode;
+ NSString *fullName;
+
+ max = [nodes count];
+ currentSerial = startSerial;
+ for (count = 0; count < max; count++)
+ {
+ curNode = [nodes objectAtIndex: count];
+ fullName = [rootName stringByAppendingFormat: @"/%@", [curNode name]];
+ [curNode setName: fullName];
+ [curNode setSerial: currentSerial];
+ [curNode setParent: parent];
+ [array addObject: curNode];
+ if ([curNode hasChildren])
+ currentSerial = [self addNodes: [curNode children]
+ atSerial: currentSerial + 1
+ forParent: currentSerial
+ withRootName: fullName
+ toArray: array];
+ else
+ currentSerial++;
+ }
+
+ return currentSerial;
+}
+
+- (NSArray *) flattenedNodes
+{
+ UIxMailTreeBlock *rootNode; // , *curNode;
+ id mailAccounts;
+// unsigned int count, max;
+
+ if (!flattenedNodes)
+ {
+ flattenedNodes = [NSMutableArray new];
+
+ if (![[self clientObject] isKindOfClass: NSClassFromString(@"SOGoMailAccounts")])
+ mailAccounts = [[self clientObject] mailAccountsFolder];
+ else
+ mailAccounts = [self clientObject];
+
+ rootNode = [self fullTreeNavigationBlockForNode: mailAccounts];
+ [self addNodes: [rootNode children]
+ atSerial: 1
+ forParent: 0
+ withRootName: @""
+ toArray: flattenedNodes];
+// max = [flattenedBlocks count];
+// for (count = 0; count < max; count++)
+// {
+// curNode = [flattenedBlocks objectAtIndex: count];
+// NSLog (@"%d: %@/%@", count, [curNode title], [curNode iconName]);
+// }
+ }
+
+ return flattenedNodes;
}
/* notifications */
-- (void)sleep {
- [self->item release]; self->item = nil;
- [self->rootNodes release]; self->rootNodes = nil;
+- (void) sleep
+{
+ [item release]; item = nil;
+ [rootNodes release]; rootNodes = nil;
[super sleep];
}