diff --git a/macosx/CelestiaAppCore.h b/macosx/CelestiaAppCore.h index 3148ff1a..6996fcaf 100644 --- a/macosx/CelestiaAppCore.h +++ b/macosx/CelestiaAppCore.h @@ -10,11 +10,11 @@ #import "CelestiaDestination.h" #import "CelestiaFavorite.h" +#import "CelestiaFavorites.h" #import "CelestiaSimulation.h" #import "CelestiaRenderer.h" @interface CelestiaAppCore : NSObject { - CelestiaFavorites* _favorites; CelestiaDestinations* _destinations; } +(CelestiaAppCore *)sharedAppCore; diff --git a/macosx/CelestiaAppCore.mm b/macosx/CelestiaAppCore.mm index 107fa686..227b0cd7 100644 --- a/macosx/CelestiaAppCore.mm +++ b/macosx/CelestiaAppCore.mm @@ -32,8 +32,6 @@ runScript(CommandSequence *); CommandParser CommandSequence -do addFavorites - */ CelestiaAppCore *_sharedCelestiaAppCore; @@ -75,17 +73,12 @@ void ContextMenuCallback(float x,float y, Selection selection) { self = [super init]; appCore = new CelestiaCore(); contextMenuCallbackInvocation = NULL; - _favorites = nil; _destinations = nil; return self; } - (void)dealloc { - if (_favorites != nil) { - [_favorites release]; - _favorites = nil; - } if (_destinations != nil) { [_destinations release]; _destinations = nil; @@ -193,18 +186,6 @@ void ContextMenuCallback(float x,float y, Selection selection) { appCore->showText([text stdString]); } --(void)readFavoritesFile -{ -// Will do this with MacOS X functionality soon - appCore->readFavoritesFile(); -} - --(void)writeFavoritesFile -{ -// Will do this with MacOS X functionality soon - appCore->writeFavoritesFile(); -} - -(void)activateFavorite:(id)fav { //NSLog(@"[CelestiaAppCore activateFavorite:%@]",fav); @@ -215,12 +196,7 @@ void ContextMenuCallback(float x,float y, Selection selection) { -(CelestiaFavorites *)favorites { - if (_favorites == nil || [_favorites favorites] != appCore->getFavorites()) { - if (_favorites != nil) - [_favorites release]; - _favorites = [[CelestiaFavorites alloc] initWithFavorites:appCore->getFavorites()]; - } - return _favorites; + return [CelestiaFavorites sharedFavorites]; } -(CelestiaDestinations *)destinations diff --git a/macosx/CelestiaController.m b/macosx/CelestiaController.m index bf6475bb..f8d516da 100644 --- a/macosx/CelestiaController.m +++ b/macosx/CelestiaController.m @@ -97,10 +97,10 @@ // Set the simulation starting time to the current system time [appCore start:[NSDate date] withTimeZone:[NSTimeZone defaultTimeZone]]; ready = YES; - menuCallback = [NSInvocation invocationWithMethodSignature:[FavoritesDrawerController instanceMethodSignatureForSelector:@selector(synchronizeFavoritesMenu:)]]; - [menuCallback setSelector:@selector(synchronizeFavoritesMenu:)]; + menuCallback = [NSInvocation invocationWithMethodSignature:[FavoritesDrawerController instanceMethodSignatureForSelector:@selector(synchronizeFavoritesMenu)]]; + [menuCallback setSelector:@selector(synchronizeFavoritesMenu)]; [menuCallback setTarget:favoritesDrawerController]; - [[appCore favorites] setSynchronize:menuCallback]; + [[CelestiaFavorites sharedFavorites] setSynchronize:menuCallback]; } - (void)dealloc diff --git a/macosx/CelestiaFavorite.h b/macosx/CelestiaFavorite.h index eeaba213..3fff9d26 100644 --- a/macosx/CelestiaFavorite.h +++ b/macosx/CelestiaFavorite.h @@ -9,11 +9,18 @@ #import #import "CelestiaUniversalCoord.h" +// parentFolder is totally vestigal crap + @interface CelestiaFavorite : NSObject { NSValue* _data; + BOOL _freeWhenDone; } -//-(void)activate:(id)sender; +-(void)activate; -(void)setName:(NSString*)name; +-(id)initWithName:(NSString*)name; +-(id)initWithName:(NSString*)name parentFolder:(CelestiaFavorite*)folder; +-(id)initWithFolderName:(NSString*)name; +-(id)initWithFolderName:(NSString*)name parentFolder:(CelestiaFavorite*)folder; -(NSString*)name; -(NSString*)selectionName; -(CelestiaUniversalCoord*)position; @@ -30,30 +37,4 @@ -(void)setName:(NSString*)name; -(NSString*)selectionName; -(NSString*)coordinateSystem; -@end - - -@interface CelestiaFavorites : NSMutableArray { - NSValue* _data; - NSMutableArray* _retain; -} --(void)synchronize; --(void)setSynchronize:(NSInvocation*)sync; --(unsigned)count; --(id)objectAtIndex:(unsigned)index; --(void)addObject:(CelestiaFavorite*)o; --(void)insertObject:(CelestiaFavorite*)o atIndex:(unsigned)index; --(void)removeLastObject; --(void)removeObjectAtIndex:(unsigned)index; --(void)replaceObjectAtIndex:(unsigned)index withObject:(CelestiaFavorite*)o; --(unsigned)depthAtIndex:(unsigned)idx; --(unsigned)firstIndexWithParentFolder:(CelestiaFavorite*)folder; --(unsigned)lastIndexWithParentFolder:(CelestiaFavorite*)folder; --(void)addNewFavorite:(NSString*)name withParentFolder:(CelestiaFavorite*)folder atIndex:(unsigned)idx; --(void)addNewFavorite:(NSString*)name withParentFolder:(CelestiaFavorite*)folder; --(void)addNewFolder:(NSString*)name withParentFolder:(CelestiaFavorite*)parentFolder atIndex:(unsigned)idx; --(void)addNewFolder:(NSString*)name withParentFolder:(CelestiaFavorite*)parentFolder; --(id)objectAtIndex:(unsigned)index parent:(CelestiaFavorite*)parent; --(unsigned)numberOfChildrenOfItem:(CelestiaFavorite*)folder; - @end \ No newline at end of file diff --git a/macosx/CelestiaFavorite.mm b/macosx/CelestiaFavorite.mm index f73b9791..9b0f731c 100644 --- a/macosx/CelestiaFavorite.mm +++ b/macosx/CelestiaFavorite.mm @@ -16,14 +16,12 @@ #import "CelestiaSimulation.h" #import "CelestiaSimulation_PrivateAPI.h" -NSInvocation *_synchronize; - @implementation CelestiaFavorite(PrivateAPI) - -(CelestiaFavorite *)initWithFavorite:(FavoritesEntry *)fav { self = [super init]; _data = [[NSValue alloc] initWithBytes:reinterpret_cast(&fav) objCType:@encode(FavoritesEntry*)]; + _freeWhenDone = NO; return self; } -(FavoritesEntry *)favorite @@ -32,21 +30,53 @@ NSInvocation *_synchronize; } @end -@implementation CelestiaFavorites(PrivateAPI) --(CelestiaFavorites *)initWithFavorites:(const FavoritesList *)dsts +@implementation CelestiaFavorite +-(void)activate { - self = [super init]; - _data = [[NSValue alloc] initWithBytes:reinterpret_cast(&dsts) objCType:@encode(FavoritesList*)]; - _retain = [[NSMutableArray arrayWithCapacity:[self count]] retain]; + [[CelestiaAppCore sharedAppCore] activateFavorite:self]; +} +-(id)initWithName:(NSString*)name +{ + return [self initWithName:name parentFolder:nil]; +} +-(id)initWithFolderName:(NSString*)name +{ + return [self initWithFolderName:name parentFolder:nil]; +} +-(id)initWithFolderName:(NSString*)name parentFolder:(CelestiaFavorite*)folder +{ + FavoritesEntry* fav = new FavoritesEntry(); + NSString *parentFolder = (folder == nil) ? @"" : [folder name]; + if (name == nil || [name isEqualToString:@""]) + name = @"untitled folder"; + fav->name = [name stdString]; + fav->isFolder = true; + fav->parentFolder = [parentFolder stdString]; + self = [self initWithFavorite:fav]; + _freeWhenDone = YES; return self; } --(FavoritesList *)favorites +-(id)initWithName:(NSString*)name parentFolder:(CelestiaFavorite*)folder { - return reinterpret_cast([_data pointerValue]); + FavoritesEntry* fav = new FavoritesEntry(); + Simulation* sim = [[[CelestiaAppCore sharedAppCore] simulation] simulation]; + NSString *parentFolder = (folder == nil) ? @"" : [folder name]; + if (name == nil) + name = [[[[CelestiaAppCore sharedAppCore] simulation] selection] name]; + if (name == nil) + name = [[[[CelestiaAppCore sharedAppCore] simulation] julianDate] description]; + fav->jd = sim->getTime(); + fav->position = sim->getObserver().getPosition(); + fav->orientation = sim->getObserver().getOrientation(); + fav->name = [name stdString]; + fav->isFolder = false; + fav->parentFolder = [parentFolder stdString]; + fav->selectionName = sim->getSelection().getName(); + fav->coordSys = sim->getFrame().coordSys; + self = [self initWithFavorite:fav]; + _freeWhenDone = YES; + return self; } -@end - -@implementation CelestiaFavorite -(unsigned)hash { return (unsigned)[_data pointerValue]; @@ -54,6 +84,10 @@ NSInvocation *_synchronize; -(void)dealloc { if (_data != nil) { + if (_freeWhenDone) { + FavoritesEntry* fav = [self favorite]; + delete fav; + } [_data release]; _data = nil; } @@ -61,15 +95,7 @@ NSInvocation *_synchronize; } -(BOOL)isEqualToFavorite:(CelestiaFavorite*)fav { - /* - return ( - [[self name] isEqualToString:[fav name]] && - [[self parentFolder] isEqualToString:[fav parentFolder]] && - [[self selectionName] isEqualToString:[fav selectionName]] && - ([self isFolder] == [fav isFolder]) && - [[self jd] isEqualToNumber:[fav jd]] - ); - */ + // pointer equality is enough in this case return ([self favorite] == [fav favorite]); } -(BOOL)isEqualToString:(NSString*)str @@ -135,220 +161,4 @@ NSInvocation *_synchronize; { return [Astro stringWithCoordinateSystem:[NSNumber numberWithInt:(int)[self favorite]->coordSys]]; } -@end - -@implementation CelestiaFavorites -+(void)initialize -{ - _synchronize = nil; -} - --(unsigned)depthAtIndex:(unsigned)idx -{ - unsigned i,d; - NSString *lastName=@""; - d=0; - for(i=0;i<=idx;++i) { - CelestiaFavorite* fav = [self objectAtIndex:i]; - if ([[fav parentFolder] isEqualToString:@""]) { - d=0; - } else if ([[fav parentFolder] isEqualToString:lastName] && [lastName length]>0) { - ++d; - } else { - --d; - } - lastName = [fav name]; - } - return d; -} --(id)objectAtIndex:(unsigned)index parent:(CelestiaFavorite*)parent -{ - /* FIXME, needs to step over children folders */ - unsigned idx = 0; - if (parent != nil) { - idx = [self firstIndexWithParentFolder:parent]; - if (idx == NSNotFound) return nil; - } - return [self objectAtIndex:(index+idx)]; -} --(unsigned)firstIndexWithParentFolder:(CelestiaFavorite*)folder -{ - unsigned begin; - NSString *folderName; - if (folder == nil) return 0; - folderName = [folder name]; - begin = [self indexOfObjectIdenticalTo:folder]; - if (begin == NSNotFound) - return NSNotFound; - return ++begin; -} --(unsigned)lastIndexWithParentFolder:(CelestiaFavorite*)folder -{ - /* FIXME, needs to step over children folders */ - unsigned begin,end,i; - NSString *folderName; - if (folder == nil) - return [self count]; - folderName = [folder name]; - begin = [self indexOfObjectIdenticalTo:folder]; - if (begin == NSNotFound) - return NSNotFound; - end = [self count]; - for (i=++begin;ijd = sim->getTime(); - fav->position = sim->getObserver().getPosition(); - fav->orientation = sim->getObserver().getOrientation(); - fav->name = [name stdString]; - fav->isFolder = false; - fav->parentFolder = [parentFolder stdString]; - fav->selectionName = sim->getSelection().getName(); - fav->coordSys = sim->getFrame().coordSys; - [self insertObject:cfav atIndex:idx]; -} - --(void)addNewFavorite:(NSString*)name withParentFolder:(CelestiaFavorite*)folder -{ - unsigned idx; - FavoritesEntry* fav = new FavoritesEntry(); - CelestiaFavorite* cfav = [[[CelestiaFavorite alloc] initWithFavorite:fav] autorelease]; - Simulation* sim = [[[CelestiaAppCore sharedAppCore] simulation] simulation]; - NSString *parentFolder = (folder == nil) ? @"" : [folder name]; - if (name == nil) - name = [[[[CelestiaAppCore sharedAppCore] simulation] selection] name]; - if (name == nil) - name = [[[[CelestiaAppCore sharedAppCore] simulation] julianDate] description]; - NSLog(@"[CelestiaFavorites addNewFavorite:%@ inFolder:%@]",name,folder); - fav->jd = sim->getTime(); - fav->position = sim->getObserver().getPosition(); - fav->orientation = sim->getObserver().getOrientation(); - fav->name = [name stdString]; - fav->isFolder = false; - fav->parentFolder = [parentFolder stdString]; - fav->selectionName = sim->getSelection().getName(); - fav->coordSys = sim->getFrame().coordSys; - idx = [self lastIndexWithParentFolder:folder]; - [self insertObject:cfav atIndex:((idx==NSNotFound)?[self count]:idx)]; -} --(void)addNewFolder:(NSString*)name withParentFolder:(CelestiaFavorite*)folder atIndex:(unsigned)idx -{ - FavoritesEntry* fav = new FavoritesEntry(); - CelestiaFavorite* cfav = [[[CelestiaFavorite alloc] initWithFavorite:fav] autorelease]; - NSString *parentFolder = ((folder == nil) ? @"" : [folder name]); - fav->parentFolder = [parentFolder stdString]; - fav->isFolder = true; - fav->name = [name stdString]; - [self insertObject:cfav atIndex:idx]; -} --(void)addNewFolder:(NSString*)name withParentFolder:(CelestiaFavorite*)folder -{ - unsigned idx; - FavoritesEntry* fav = new FavoritesEntry(); - CelestiaFavorite* cfav = [[[CelestiaFavorite alloc] initWithFavorite:fav] autorelease]; - NSString *parentFolder = (folder == nil) ? @"" : [folder name]; - fav->parentFolder = [parentFolder stdString]; - fav->isFolder = true; - fav->name = [name stdString]; - idx = [self firstIndexWithParentFolder:folder]; - [self insertObject:cfav atIndex:idx]; -} --(unsigned)count -{ - if (![self favorites]) - return 0; - return [self favorites]->size(); -} --(id)objectAtIndex:(unsigned)index -{ - CelestiaFavorite* orig = [[[CelestiaFavorite alloc] initWithFavorite:(*[self favorites])[index]] autorelease]; - unsigned idx = [_retain indexOfObject:orig]; - if (idx == NSNotFound) { - [_retain addObject:orig]; - return orig; - } - return [_retain objectAtIndex:idx]; -} --(void)addObject:(CelestiaFavorite*)o -{ - [_retain addObject:o]; - [self favorites]->push_back([o favorite]); - [self synchronize]; -} --(void)insertObject:(CelestiaFavorite*)o atIndex:(unsigned)index -{ - [_retain addObject:o]; - [self favorites]->insert([self favorites]->begin()+index, [o favorite]); - [self synchronize]; -} --(void)removeLastObject -{ - [_retain removeObject:[self lastObject]]; - [self favorites]->pop_back(); - [self synchronize]; -} --(void)removeObjectAtIndex:(unsigned)index -{ - [_retain removeObject:[self objectAtIndex:index]]; - [self favorites]->erase([self favorites]->begin()+index); - [self synchronize]; -} --(void)replaceObjectAtIndex:(unsigned)index withObject:(CelestiaFavorite*)o -{ - [self removeObjectAtIndex:index]; - [self insertObject:o atIndex:index]; -} --(void)setSynchronize:(NSInvocation*)sync -{ - if (_synchronize != nil) { - [_synchronize release]; - _synchronize = nil; - } - _synchronize = [sync retain]; - [_synchronize setArgument:&self atIndex:2]; -} --(void)synchronize -{ - NSLog(@"[CelestiaFavorites synchronize]"); - //NSLog(@"%@",self); - if (_synchronize == nil) - return; - [_synchronize invoke]; -} --(void)dealloc -{ - if (_data != nil) { - [_data release]; - _data = nil; - } - if (_retain != nil) { - [_retain release]; - _retain = nil; - } - [super dealloc]; -} @end \ No newline at end of file diff --git a/macosx/CelestiaFavorite_PrivateAPI.h b/macosx/CelestiaFavorite_PrivateAPI.h index b0387a22..ef71c62b 100644 --- a/macosx/CelestiaFavorite_PrivateAPI.h +++ b/macosx/CelestiaFavorite_PrivateAPI.h @@ -12,11 +12,4 @@ @interface CelestiaFavorite(PrivateAPI) -(CelestiaFavorite*)initWithFavorite:(FavoritesEntry*)fav; -(FavoritesEntry*)favorite; -@end - - -@interface CelestiaFavorites(PrivateAPI) --(CelestiaFavorites*)initWithFavorites:(const FavoritesList*)favs; --(FavoritesList*)favorites; -@end - +@end \ No newline at end of file diff --git a/macosx/CelestiaFavorites.h b/macosx/CelestiaFavorites.h new file mode 100644 index 00000000..2361b20e --- /dev/null +++ b/macosx/CelestiaFavorites.h @@ -0,0 +1,20 @@ +// +// CelestiaFavorites.h +// celestia +// +// Created by Bob Ippolito on Thu Jun 20 2002. +// Copyright (c) 2002 Chris Laurel. All rights reserved. +// + +#import +#import "CelestiaFavorite.h" +#import "myTree.h" + + +@interface CelestiaFavorites : MyTree +-(void)setSynchronize:(NSInvocation*)synchronize; +-(void)synchronize; ++(CelestiaFavorites*)sharedFavorites; +-(MyTree*)addNewFavorite:(NSString*)name; +-(MyTree*)addNewFolder:(NSString*)name; +@end diff --git a/macosx/CelestiaFavorites.m b/macosx/CelestiaFavorites.m new file mode 100644 index 00000000..a11af7fe --- /dev/null +++ b/macosx/CelestiaFavorites.m @@ -0,0 +1,53 @@ +// +// CelestiaFavorites.m +// celestia +// +// Created by Bob Ippolito on Thu Jun 20 2002. +// Copyright (c) 2002 Chris Laurel. All rights reserved. +// + +#import "CelestiaFavorites.h" +#import "CelestiaFavorite.h" +@implementation CelestiaFavorites +static NSInvocation* _synchronize; +static CelestiaFavorites* _celestiaFavorites; +-(void)setSynchronize:(NSInvocation*)synchronize +{ + if (_synchronize != nil) + [_synchronize autorelease]; + _synchronize = [synchronize retain]; +} +-(void)synchronize +{ + if (_synchronize != nil) + [_synchronize invoke]; +} +-(NSString*)description +{ + return [NSString stringWithFormat:@"",[self numberOfChildren]]; +} +-(MyTree*)addNewFavorite:(NSString*)name +{ + MyTree* obj = [[[MyTree alloc] initWithNode:[[[CelestiaFavorite alloc] initWithName:name] autorelease] parent:self] autorelease]; + [[self children] addObject:obj]; + return obj; +} +-(MyTree*)addNewFolder:(NSString*)name +{ + MyTree* obj = [[[MyTree alloc] initWithNode:[[[CelestiaFavorite alloc] initWithFolderName:name] autorelease] parent:self children:[NSArray array]] autorelease]; + [[self children] addObject:obj]; + return obj; +} ++(void)initialize +{ + _celestiaFavorites = nil; + _synchronize = nil; +} ++(CelestiaFavorites*)sharedFavorites +{ + if (_celestiaFavorites != nil) + return _celestiaFavorites; + _celestiaFavorites = [[CelestiaFavorites alloc] initWithNode:nil parent:nil children:[NSArray array]]; + return _celestiaFavorites; +} +@end diff --git a/macosx/ContextOutlineView.h b/macosx/ContextOutlineView.h index 08b3b89d..732eb8e0 100644 --- a/macosx/ContextOutlineView.h +++ b/macosx/ContextOutlineView.h @@ -1,6 +1,7 @@ /* ContextOutlineView */ #import +#import "NSOutlineView_Extensions.h" @interface ContextOutlineView : NSOutlineView { } diff --git a/macosx/English.lproj/MainMenu.nib/classes.nib b/macosx/English.lproj/MainMenu.nib/classes.nib index 69768ba6..15c490e8 100644 --- a/macosx/English.lproj/MainMenu.nib/classes.nib +++ b/macosx/English.lproj/MainMenu.nib/classes.nib @@ -29,6 +29,7 @@ LANGUAGE = ObjC; OUTLETS = { coordinateField = NSTextField; + favoritesDrawerController = id; jdField = NSTextField; nameField = NSTextField; orientationField = NSTextField; @@ -42,7 +43,7 @@ LANGUAGE = ObjC; OUTLETS = { drawer = NSDrawer; - favoriteInfoWindowController = FavoriteInfoWindowController; + favoriteInfoWindowController = id; favoritesContextMenu = NSMenu; favoritesMenu = NSMenu; outlineView = ContextOutlineView; diff --git a/macosx/English.lproj/MainMenu.nib/info.nib b/macosx/English.lproj/MainMenu.nib/info.nib index e970437e..9544d1e2 100644 --- a/macosx/English.lproj/MainMenu.nib/info.nib +++ b/macosx/English.lproj/MainMenu.nib/info.nib @@ -3,7 +3,7 @@ IBDocumentLocation - 45 242 515 457 0 0 1152 746 + 66 156 515 457 0 0 1152 746 IBEditorPositions 242 @@ -11,7 +11,7 @@ 29 19 661 452 44 0 0 1152 746 296 - 491 337 170 341 0 0 1152 746 + 491 338 170 341 0 0 1152 746 335 522 588 98 114 0 0 1152 746 342 @@ -25,11 +25,9 @@ IBOpenObjects - 242 - 296 - 352 + 21 IBSystem Version - 5S60 + 5S66 diff --git a/macosx/English.lproj/MainMenu.nib/objects.nib b/macosx/English.lproj/MainMenu.nib/objects.nib index 34c31796..109d3aa1 100644 Binary files a/macosx/English.lproj/MainMenu.nib/objects.nib and b/macosx/English.lproj/MainMenu.nib/objects.nib differ diff --git a/macosx/FavoriteInfoWindowController.m b/macosx/FavoriteInfoWindowController.m index 9d3e600c..c446f931 100644 --- a/macosx/FavoriteInfoWindowController.m +++ b/macosx/FavoriteInfoWindowController.m @@ -31,9 +31,8 @@ - (IBAction)navigateTo:(id)sender { [[self window] performClose:self]; - if (_fav == nil) - return; - [(FavoritesDrawerController*)favoritesDrawerController activateFavorite:_fav]; + if (_fav != nil) + [(FavoritesDrawerController*)favoritesDrawerController activateFavorite:_fav]; } @end diff --git a/macosx/FavoritesDrawerController.h b/macosx/FavoritesDrawerController.h index f8c04e2d..60d971c7 100644 --- a/macosx/FavoritesDrawerController.h +++ b/macosx/FavoritesDrawerController.h @@ -8,45 +8,52 @@ @interface FavoritesDrawerController : NSObject { + NSArray *draggedNodes; IBOutlet NSDrawer *drawer; IBOutlet ContextOutlineView *outlineView; IBOutlet NSMenu *favoritesMenu; IBOutlet NSMenu *favoritesContextMenu; IBOutlet id favoriteInfoWindowController; } +-(NSArray*)selectedNodes; +-(NSArray*)draggedNodes; -(void)activateFavorite:(CelestiaFavorite*)fav; -(void)close; -(IBAction)close:(id)sender; -- (NSMenu *)outlineView:(NSOutlineView *)outlineView +-(NSMenu *)outlineView:(NSOutlineView *)outlineView contextMenuForItem:(id)item; -(IBAction)addNewFavorite:(id)sender; -(IBAction)addNewFolder:(id)sender; -(IBAction)doubleClick:(id)sender; --(void)synchronizeFavoritesMenu:(CelestiaFavorites*)favs; +-(void)synchronizeFavoritesMenu; -(id)outlineView:(NSOutlineView*)olv child:(int)index ofItem:(id)item; -(BOOL)outlineView:(NSOutlineView*)olv isItemExpandable:(id)item; -(int)outlineView:(NSOutlineView *)olv numberOfChildrenOfItem:(id)item; -(id)outlineView:(NSOutlineView *)olv objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; -(void)outlineView:(NSOutlineView *)olv setObjectValue:(id)object forTableColumn:(NSTableColumn *)tableColumn byItem:(id)item; --(void)outlineView:(NSOutlineView*)olv deleteItem:(CelestiaFavorite*)item; +-(void)outlineView:(NSOutlineView*)olv deleteItem:(id)item; -(void)outlineView:(NSOutlineView*)olv editItem:(id)item; -(void)outlineViewSelectionDidChange:(NSNotification*)notification; /* -(BOOL)outlineView:(NSOutlineView *)olv shouldExpandItem:(id)item; -(void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item; +*/ -(BOOL)outlineView:(NSOutlineView *)olv writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard; -(unsigned int)outlineView:(NSOutlineView*)olv validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(int)childIndex; --(void)_performDropOperation:(id )info onNode:(TreeNode*)parentNode atIndex:(int)childIndex; +-(void)_performDropOperation:(id )info onNode:(id)pnode atIndex:(int)childIndex; -(BOOL)outlineView:(NSOutlineView*)olv acceptDrop:(id )info item:(id)targetItem childIndex:(int)childIndex; -*/ - @end @interface CelestiaFavorite(ViewAPI) --(NSMenuItem*)menuItem; --(NSMenuItem*)setupMenuItem:(NSMenuItem*)menuItem; +-(NSMenuItem*)favoriteMenuItem; +-(NSMenuItem*)setupFavoriteMenuItem:(NSMenuItem*)menuItem; @end @interface CelestiaFavorites(ViewAPI) --(void)synchronizeMenu:(NSMenu*)menu atIndex:(unsigned)count; +-(NSArray*)favoriteMenuItems; +@end + +@interface MyTree(ViewAPI) +-(void)activate; +-(NSMenuItem*)favoriteMenuItem; @end diff --git a/macosx/FavoritesDrawerController.m b/macosx/FavoritesDrawerController.m index a17c95f0..b1a47d0b 100644 --- a/macosx/FavoritesDrawerController.m +++ b/macosx/FavoritesDrawerController.m @@ -1,7 +1,8 @@ #import "FavoritesDrawerController.h" #import "CelestiaFavorite.h" -#import "CelestiaAppCore.h" - +#import "CelestiaFavorites.h" +#define SAFENODE(node) ((MyTree*)((node == nil) ? [CelestiaFavorites sharedFavorites] : node)) +#define DragDropSimplePboardType @"CelestiaFavoriteOutlineViewPboardType" /* @implementation NSMenuItem(DebuggingAPI) -(NSString*)description @@ -10,17 +11,16 @@ } @end */ - @implementation CelestiaFavorite(ViewAPI) --(NSMenuItem*)menuItem +-(NSMenuItem*)favoriteMenuItem { - NSMenuItem* menuItem = [[[NSMenuItem alloc] initWithTitle:[self name] action:@selector(activateFavorite:) keyEquivalent:@""] autorelease]; - return [self setupMenuItem:menuItem]; + NSMenuItem* menuItem = [[[NSMenuItem alloc] initWithTitle:[self name] action:([self isFolder] ? nil : @selector(activate)) keyEquivalent:@""] autorelease]; + return [self setupFavoriteMenuItem:menuItem]; } --(NSMenuItem*)setupMenuItem:(NSMenuItem*)menuItem +-(NSMenuItem*)setupFavoriteMenuItem:(NSMenuItem*)menuItem { - [menuItem setTarget:[CelestiaAppCore sharedAppCore]]; - [menuItem setAction:@selector(activateFavorite:)]; + [menuItem setTarget:self]; + [menuItem setAction:([self isFolder] ? nil : @selector(activate))]; [menuItem setTitle:[self name]]; [menuItem setRepresentedObject:self]; [menuItem setKeyEquivalent:@""]; @@ -30,33 +30,51 @@ @end @implementation CelestiaFavorites(ViewAPI) --(void)synchronizeMenu:(NSMenu*)menu atIndex:(unsigned)count +-(NSArray*)favoriteMenuItems { - NSEnumerator *enumerator = [self objectEnumerator]; - CelestiaFavorite *fav; - NSMutableArray *menuStack = [NSMutableArray arrayWithCapacity:[self count]]; - //NSLog(@"[CelestiaFavorites synchronizeMenu:%@ atIndex:%d]",menu,count); - while ((unsigned)[menu numberOfItems]>count) - [menu removeItemAtIndex:[menu numberOfItems]-1]; - //NSString *lastParent=@""; - [menuStack addObject:menu]; - /* FIXME */ - while ((fav = [enumerator nextObject]) != nil) { - NSMenuItem* menuItem = [fav menuItem]; - if ([[fav parentFolder] isEqualToString:@""]) - [menuStack removeObjectsInRange:NSMakeRange(1,[menuStack count]-1)]; - /*if ([fav isFolder]) { - NSMenu *subMenu = [[[NSMenu alloc] initWithTitle:[fav name]] autorelease]; - [menuItem setSubmenu:subMenu]; - [menuStack addObject:subMenu]; - }*/ - [[menuStack lastObject] addItem:menuItem]; - } - //NSLog(@"[CelestiaFavorites synchronizeMenu:%@ atIndex:%d]",menu,count); + NSEnumerator *enumerator = [[self children] objectEnumerator]; + MyTree* node = nil; + NSMutableArray* menuItems = [NSMutableArray arrayWithCapacity:[[self children] count]]; + //NSLog(@"[CelestiaFavorites favoriteMenuItems]"); + while ((node = [enumerator nextObject]) != nil) + [menuItems addObject:[node favoriteMenuItem]]; + return (NSArray*)menuItems; +} +@end +@implementation MyTree(ViewAPI) +-(void)activate +{ + [(CelestiaFavorite*)[self nodeValue] activate]; +} +-(NSMenuItem*)favoriteMenuItem +{ + NSEnumerator* enumerator = nil; + NSMenu* subMenu = nil; + NSMenuItem* menuItem = [[self nodeValue] favoriteMenuItem]; + MyTree* node = nil; + //NSLog(@"[MyTree favoriteMenuItem]"); + if ([self isLeaf]) + return menuItem; + enumerator = [[self children] objectEnumerator]; + subMenu = [[[NSMenu alloc] initWithTitle:[[self nodeValue] name]] autorelease]; + while ((node = [enumerator nextObject]) != nil) + [subMenu addItem:[node favoriteMenuItem]]; + [menuItem setSubmenu:subMenu]; + [menuItem setTarget:menuItem]; + [menuItem setAction:@selector(submenuAction:)]; + return menuItem; } @end @implementation FavoritesDrawerController +-(NSArray*)selectedNodes +{ + return [outlineView allSelectedItems]; +} +-(NSArray*)draggedNodes +{ + return draggedNodes; +} -(void)close { [drawer close]; @@ -67,61 +85,75 @@ } -(void)activateFavorite:(CelestiaFavorite*)fav { - [[CelestiaAppCore sharedAppCore] activateFavorite:fav]; + id menuItem = fav; + if ([menuItem isKindOfClass:[NSMenuItem class]]) + fav = [(NSMenuItem*)menuItem representedObject]; + [fav activate]; [outlineView deselectAll:self]; [drawer close]; } -(void)awakeFromNib { + draggedNodes = nil; [outlineView setVerticalMotionCanBeginDrag: YES]; [outlineView setTarget:self]; [outlineView setDoubleAction:@selector(doubleClick:)]; + [outlineView registerForDraggedTypes:[NSArray arrayWithObjects:DragDropSimplePboardType, nil]]; [favoritesMenu setAutoenablesItems:NO]; } -(IBAction)addNewFavorite:(id)sender { - CelestiaFavorites* favs = [[CelestiaAppCore sharedAppCore] favorites]; + CelestiaFavorites* favs = [CelestiaFavorites sharedFavorites]; + MyTree* node = nil; //NSLog(@"[FavoritesDrawerController addNewFavorite:%@]",sender); - [favs addNewFavorite:nil withParentFolder:nil]; - [self outlineView:outlineView editItem:[favs lastObject]]; + node = [favs addNewFavorite:nil]; + [[CelestiaFavorites sharedFavorites] synchronize]; + [self outlineView:outlineView editItem:node]; } -(IBAction)addNewFolder:(id)sender { - CelestiaFavorites* favs = [[CelestiaAppCore sharedAppCore] favorites]; + CelestiaFavorites* favs = [CelestiaFavorites sharedFavorites]; + MyTree* node = nil; //NSLog(@"[FavoritesDrawerController addNewFavorite:%@]",sender); - [favs addNewFolder:@"untitled folder" withParentFolder:nil]; - [self outlineView:outlineView editItem:[favs lastObject]]; + node = [favs addNewFolder:@"untitled folder"]; + [[CelestiaFavorites sharedFavorites] synchronize]; + [self outlineView:outlineView editItem:node]; } -(IBAction)doubleClick:(id)sender { - NSLog(@"[FavoritesDrawerController doubleClick:%@]",sender); + //NSLog(@"[FavoritesDrawerController doubleClick:%@]",sender); if ([outlineView numberOfSelectedRows]==1) - [self activateFavorite:[outlineView itemAtRow:[outlineView selectedRow]]]; + [self activateFavorite:[[outlineView itemAtRow:[outlineView selectedRow]] nodeValue]]; } --(void)synchronizeFavoritesMenu:(CelestiaFavorites*)favs +-(void)synchronizeFavoritesMenu { - //NSLog(@"[FavoritesDrawerController synchronizeFavoritesMenu:]"); - [[[CelestiaAppCore sharedAppCore] favorites] synchronizeMenu:favoritesMenu atIndex:3]; + NSEnumerator *enumerator = [[[CelestiaFavorites sharedFavorites] favoriteMenuItems] objectEnumerator]; + NSMenuItem *menuItem = nil; + // remove old menu items + while ([favoritesMenu numberOfItems]>3) + [favoritesMenu removeItemAtIndex:[favoritesMenu numberOfItems]-1]; + while ((menuItem = [enumerator nextObject]) != nil) + [favoritesMenu addItem:menuItem]; [outlineView reloadData]; } -(id)outlineView:(NSOutlineView*)olv child:(int)index ofItem:(id)item { id rval; //NSLog(@"[FavoritesDrawerController outlineview:%@ child:%d ofItem:%@]",olv,index,item); - rval = [[[CelestiaAppCore sharedAppCore] favorites] objectAtIndex:index parent:(CelestiaFavorite*)item]; + rval = [SAFENODE(item) childAtIndex:index]; //NSLog(@"rval = %@",rval); return rval; } -(BOOL)outlineView:(NSOutlineView*)olv isItemExpandable:(id)item { //NSLog(@"[FavoritesDrawerController outlineview:%@ itemIsExpandable:%@]",olv,item); - return [(CelestiaFavorite*)item isFolder]; + return ![SAFENODE(item) isLeaf]; } -(int)outlineView:(NSOutlineView *)olv numberOfChildrenOfItem:(id)item { int rval; //NSLog(@"[FavoritesDrawerController outlineview:%@ numberOfChildrenOfItem:%@]",olv,item); - rval = [[[CelestiaAppCore sharedAppCore] favorites] numberOfChildrenOfItem:(CelestiaFavorite*)item]; + rval = [SAFENODE(item) numberOfChildren]; //NSLog(@"rval = %d",rval); return rval; } @@ -130,9 +162,9 @@ id objectValue = nil; //NSLog(@"[FavoritesDrawerController outlineview:%@ objectValueForTableColumn:%@ byItem:%@]",olv,tableColumn,item); if([[tableColumn identifier] isEqualToString: @"NAME"]) { - objectValue = [(CelestiaFavorite*)item name]; - } else if([[tableColumn identifier] isEqualToString: @"SELECTION"] && ![(CelestiaFavorite*)item isFolder]) { - objectValue = [(CelestiaFavorite*)item selectionName]; + objectValue = [(CelestiaFavorite*)[SAFENODE(item) nodeValue] name]; + } else if([[tableColumn identifier] isEqualToString: @"SELECTION"] && [SAFENODE(item) isLeaf]) { + objectValue = [(CelestiaFavorite*)[SAFENODE(item) nodeValue] selectionName]; } //NSLog(@"rval = %@",objectValue); return objectValue; @@ -142,9 +174,9 @@ { //NSLog(@"[FavoritesDrawerController outlineview:%@ setObjectValue:%@ forTableColumn:%@ byItem:%@]",olv,object,tableColumn,item); if([[tableColumn identifier] isEqualToString: @"NAME"]) { - [(CelestiaFavorite*)item setName: object]; - [[[CelestiaAppCore sharedAppCore] favorites] synchronize]; - [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:(CelestiaFavorite*)item]; + [(CelestiaFavorite*)[SAFENODE(item) nodeValue] setName: object]; + [[CelestiaFavorites sharedFavorites] synchronize]; + [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:(CelestiaFavorite*)[SAFENODE(item) nodeValue]]; } } @@ -155,7 +187,7 @@ - (NSMenu *)outlineView:(NSOutlineView *)olv contextMenuForItem:(id)item { - CelestiaFavorite* fav = (CelestiaFavorite*)item; + MyTree* node = SAFENODE(item); NSMenu* contextMenu = [favoritesContextMenu copy]; NSInvocation* editInv = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(outlineView:editItem:)]]; NSInvocation* delInv = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(outlineView:deleteItem:)]]; @@ -184,7 +216,7 @@ contextMenuForItem:(id)item item = arr; else [olv selectRow:[olv rowForItem:item] byExtendingSelection:NO]; - if ([fav isFolder] || multipleItems) { + if (![node isLeaf] || multipleItems) { [contextMenu removeItemAtIndex:0]; [contextMenu removeItemAtIndex:0]; [contextMenu removeItemAtIndex:0]; @@ -194,9 +226,10 @@ contextMenuForItem:(id)item NSMenuItem* showItem = [contextMenu itemAtIndex:1]; [showItem setTarget:favoriteInfoWindowController]; [showItem setAction:@selector(showWindow:)]; - [fav setupMenuItem:navItem]; + [(CelestiaFavorite*)[node nodeValue] setupFavoriteMenuItem:navItem]; [navItem setTarget:self]; [navItem setTitle:title]; + [navItem setAction:@selector(activateFavorite:)]; } if (multipleItems) { [contextMenu removeItemAtIndex:0]; @@ -216,11 +249,15 @@ contextMenuForItem:(id)item [delItem setAction:@selector(invoke)]; return contextMenu; } -- (void)outlineView:(NSOutlineView*)olv editItem:(CelestiaFavorite*)item +- (void)outlineView:(NSOutlineView*)olv editItem:(id)item { int row = [olv rowForItem:item]; //NSLog(@"[FavoritesDrawerController outlineView:%@ editItem:%@]",olv,item); //NSLog(@"row = %d",row); // -1 ?? + if (row<0) { + NSLog(@"row is -1"); + return; + } [olv selectRow:row byExtendingSelection:NO]; [olv editColumn:[olv columnWithIdentifier:@"NAME"] row:row withEvent:nil select:YES]; } @@ -228,11 +265,11 @@ contextMenuForItem:(id)item - (void)outlineView:(NSOutlineView*)olv deleteItem:(id)item { //NSLog(@"[FavoritesDrawerController outlineView:%@ deleteItem:%@]",olv,item); - CelestiaFavorites *favs = [[CelestiaAppCore sharedAppCore] favorites]; - if ([item isKindOfClass:[CelestiaFavorite class]]) - [favs removeObject:(CelestiaFavorite*)item]; + if ([item isKindOfClass:[MyTree class]]) + [item removeFromParent]; else - [favs removeObjectsInArray:(NSArray*)item]; + [(NSArray*)item makeObjectsPerformSelector:@selector(removeFromParent)]; + [[CelestiaFavorites sharedFavorites] synchronize]; [olv deselectAll:self]; [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:nil]; } @@ -241,7 +278,7 @@ contextMenuForItem:(id)item { NSOutlineView* olv = [notification object]; if ([olv numberOfSelectedRows]==1) { - [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:[olv itemAtRow:[olv selectedRow]]]; + [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:[[olv itemAtRow:[olv selectedRow]] nodeValue]]; } else { [(FavoriteInfoWindowController*)favoriteInfoWindowController updateFavorite:nil]; } @@ -251,11 +288,12 @@ contextMenuForItem:(id)item { BOOL rval; NSLog(@"[FavoritesDrawerController outlineview:%@ shouldExpandItem:%@]",olv,item); - rval = [(CelestiaFavorite*)item isFolder]; + rval = ![SAFENODE(item) isLeaf]; NSLog(@"rval = %@",((rval)?@"YES":@"NO")); return rval; } - +*/ +/* - (void)outlineView:(NSOutlineView *)olv willDisplayCell:(NSCell *)cell forTableColumn:(NSTableColumn *)tableColumn item:(id)item { // NSLog(@"[FavoritesDrawerController outlineview:%@ willDisplayCell:%@ forTableColumn:%@ item:0x%X]",olv,cell,tableColumn,item); @@ -273,9 +311,10 @@ contextMenuForItem:(id)item // ================================================================ // NSOutlineView data source methods. (dragging related) // ================================================================ -/* + - (BOOL)outlineView:(NSOutlineView *)olv writeItems:(NSArray*)items toPasteboard:(NSPasteboard*)pboard { + //NSLog(@"[FavoritesDrawerController outlineView:%@ writeItems:%@ toPasteboard:%@]",olv,items,pboard); draggedNodes = items; // Don't retain since this is just holding temporaral drag information, and it is only used during a drag! We could put this in the pboard actually. // Provide data for our custom type, and simple NSStrings. @@ -292,34 +331,40 @@ contextMenuForItem:(id)item - (unsigned int)outlineView:(NSOutlineView*)olv validateDrop:(id )info proposedItem:(id)item proposedChildIndex:(int)childIndex { // This method validates whether or not the proposal is a valid one. Returns NO if the drop should not be allowed. - SimpleTreeNode *targetNode = item; + MyTree *targetNode = item; BOOL targetNodeIsValid = YES; - if ([self onlyAcceptDropOnRoot]) { - targetNode = nil; - childIndex = NSOutlineViewDropOnItemIndex; - } else { - BOOL isOnDropTypeProposal = childIndex==NSOutlineViewDropOnItemIndex; - - // Refuse if: dropping "on" the view itself unless we have no data in the view. - if (targetNode==nil && childIndex==NSOutlineViewDropOnItemIndex && [treeData numberOfChildren]!=0) - targetNodeIsValid = NO; + BOOL isOnDropTypeProposal = childIndex==NSOutlineViewDropOnItemIndex; + //NSLog(@"[FavoritesDrawerController outlineView:%@ validateDrop:%@ proposedItem:%@ proposedChildIndex:%d]",olv,info,item,childIndex); + // Refuse if: dropping "on" the view itself unless we have no data in the view. + /* + if (targetNode==nil && isOnDropTypeProposal==YES && [self outlineView:olv numberOfChildrenOfItem:nil]!=0) + targetNodeIsValid = NO; + */ + if (targetNode==nil && isOnDropTypeProposal==YES)// && [self allowOnDropOnLeaf]==NO) + targetNodeIsValid = NO; + + if (targetNodeIsValid && [targetNode isLeaf]) + targetNodeIsValid = NO; + + if (isOnDropTypeProposal) + targetNodeIsValid = NO; - if (targetNode==nil && childIndex==NSOutlineViewDropOnItemIndex && [self allowOnDropOnLeaf]==NO) - targetNodeIsValid = NO; - - // Refuse if: we are trying to do something which is not allowed as specified by the UI check boxes. - if (targetNodeIsValid && isOnDropTypeProposal==NO && [self allowBetweenDrop]==NO || - [NODE_DATA(targetNode) isGroup] && isOnDropTypeProposal==YES && [self allowOnDropOnGroup]==NO || - [NODE_DATA(targetNode) isLeaf ] && isOnDropTypeProposal==YES && [self allowOnDropOnLeaf]==NO) - targetNodeIsValid = NO; - - // Check to make sure we don't allow a node to be inserted into one of its descendants! - if (targetNodeIsValid && ([info draggingSource]==outlineView) && [[info draggingPasteboard] availableTypeFromArray:[NSArray arrayWithObject: DragDropSimplePboardType]] != nil) { - NSArray *_draggedNodes = [[[info draggingSource] dataSource] draggedNodes]; - targetNodeIsValid = ![targetNode isDescendantOfNodeInArray: _draggedNodes]; - } + // Check to make sure we don't allow a node to be inserted into one of its descendants! + if (targetNodeIsValid && ([info draggingSource]==outlineView) && [[info draggingPasteboard] availableTypeFromArray:[NSArray arrayWithObject: DragDropSimplePboardType]] != nil) { + NSArray* _draggedNodes = [[[info draggingSource] dataSource] draggedNodes]; + //NSEnumerator* enumerator = [_draggedNodes objectEnumerator]; + //MyTree* node = nil; + targetNodeIsValid = ![targetNode isDescendantOfNodeInArray: _draggedNodes]; + /* + while ((node = [enumerator nextObject]) != nil) + if ([[node parent] isEqualTo:SAFENODE(item)] && !isOnDropTypeProposal && childIndex >= [SAFENODE(item) numberOfChildren]) { + targetNodeIsValid = NO; + break; + } + */ } + // Set the item and child index in case we computed a retargeted one. [outlineView setDropItem:targetNode dropChildIndex:childIndex]; @@ -327,55 +372,45 @@ contextMenuForItem:(id)item return targetNodeIsValid ? NSDragOperationGeneric : NSDragOperationNone; } -- (void)_performDropOperation:(id )info onNode:(TreeNode*)parentNode atIndex:(int)childIndex { +- (void)_performDropOperation:(id )info onNode:(id)pnode atIndex:(int)childIndex { // Helper method to insert dropped data into the model. - NSPasteboard * pboard = [info draggingPasteboard]; - NSMutableArray * itemsToSelect = nil; - - // Do the appropriate thing depending on wether the data is DragDropSimplePboardType or NSStringPboardType. + NSPasteboard* pboard = [info draggingPasteboard]; + NSMutableArray* itemsToSelect = nil; + MyTree* parentNode = SAFENODE(pnode); + //NSLog(@"[FavoritesDrawerController _performDropOperation:%@ onNode:%@ atIndex:%d]",info,pnode,childIndex); + //NSLog(@"parentNode = %@",parentNode); if ([pboard availableTypeFromArray:[NSArray arrayWithObjects:DragDropSimplePboardType, nil]] != nil) { - AppController *dragDataSource = [[info draggingSource] dataSource]; - NSArray *_draggedNodes = [TreeNode minimumNodeCoverFromNodesInArray: [dragDataSource draggedNodes]]; + FavoritesDrawerController *dragDataSource = [[info draggingSource] dataSource]; + NSArray *_draggedNodes = [MyTree minimumNodeCoverFromNodesInArray: [dragDataSource draggedNodes]]; NSEnumerator *draggedNodesEnum = [_draggedNodes objectEnumerator]; - SimpleTreeNode *_draggedNode = nil, *_draggedNodeParent = nil; - + MyTree *_draggedNode = nil, *_draggedNodeParent = nil; + //MyTree* favs = [CelestiaFavorites sharedFavorites]; itemsToSelect = [NSMutableArray arrayWithArray:[self selectedNodes]]; - + /* + NSLog(@"dragDataSource = %@",dragDataSource); + NSLog(@"_draggedNodes = %@",_draggedNodes); + NSLog(@"itemsToSelect = %@",itemsToSelect); + */ while ((_draggedNode = [draggedNodesEnum nextObject])) { - _draggedNodeParent = (SimpleTreeNode*)[_draggedNode nodeParent]; + _draggedNodeParent = [_draggedNode parent]; if (parentNode==_draggedNodeParent && [parentNode indexOfChild: _draggedNode])info item:(id)targetItem childIndex:(int)childIndex { - TreeNode * parentNode = nil; - + MyTree * parentNode = nil; + //NSLog(@"[FavoritesDrawerController outlineView:%@ acceptDrop:%@ item:%@ childIndex:%d]",olv,info,targetItem,childIndex); // Determine the parent to insert into and the child index to insert at. - if ([NODE_DATA(targetItem) isLeaf]) { - parentNode = (SimpleTreeNode*)(childIndex==NSOutlineViewDropOnItemIndex ? [targetItem nodeParent] : targetItem); - childIndex = (childIndex==NSOutlineViewDropOnItemIndex ? [[targetItem nodeParent] indexOfChild: targetItem]+1 : 0); - if ([NODE_DATA(parentNode) isLeaf]) [NODE_DATA(parentNode) setIsLeaf:NO]; - } else { - parentNode = SAFENODE(targetItem); - childIndex = (childIndex==NSOutlineViewDropOnItemIndex?0:childIndex); - } - - [self _performDropOperation:info onNode:parentNode atIndex:childIndex]; - + parentNode = (MyTree*)(targetItem ? targetItem : [CelestiaFavorites sharedFavorites]);//SAFENODE(targetItem); + childIndex = (childIndex==NSOutlineViewDropOnItemIndex ? 0 : childIndex); + [self _performDropOperation:info onNode:parentNode atIndex:childIndex]; return YES; } -*/ + @end diff --git a/macosx/MyTree.h b/macosx/MyTree.h new file mode 100644 index 00000000..0bdd16b7 --- /dev/null +++ b/macosx/MyTree.h @@ -0,0 +1,62 @@ +// +// MyTree.h +// celestia +// +// Created by Bob Ippolito on Thu Jun 20 2002. +// Copyright (c) 2002 Chris Laurel. All rights reserved. +// + +#import +#import "NSArray_Extensions.h" + +@interface MyVector : NSMutableArray { + NSMutableArray *_array; + Class _myClass; +} +-(id)initWithClass:(Class)myClass; +-(void)addObject:(id)obj; +-(void)insertObject:(id)obj atIndex:(unsigned)idx; +-(void)removeLastObject; +-(void)removeObjectAtIndex:(unsigned)idx; +-(void)replaceObjectAtIndex:(unsigned)idx withObject:(id)obj; +-(unsigned)count; +-(id)objectAtIndex:(unsigned)idx; +@end + +@interface MyTree : NSObject { + id _nodeValue; + MyVector* _children; + MyTree* _parent; +} +// for initializing a tree root node +-(id)init; +// initializing a leaf node +-(id)initWithNode:(id)obj parent:(MyTree*)parent; +// initializing a branch node +-(id)initWithNode:(id)obj parent:(MyTree*)parent children:(NSArray*)children; +-(MyVector*)children; +-(void)setNode:(id)obj; +-(void)setChildren:(NSArray*)children; +-(void)setParent:(MyTree*)parent; +-(MyTree*)parent; +-(id)nodeValue; +-(BOOL)isLeaf; +-(BOOL)isDescendantOfNode:(MyTree*)node; +-(BOOL)isDescendantOfNodeInArray:(NSArray*)array; ++(NSArray*)minimumNodeCoverFromNodesInArray:(NSArray*)allNodes; + +- (void)insertChild:(MyTree*)child atIndex:(int)index; +- (void)insertChildren:(NSArray*)children atIndex:(int)index; +- (void)removeChild:(MyTree*)child; +- (void)removeFromParent; + +- (int)indexOfChild:(MyTree*)child; +- (int)indexOfChildIdenticalTo:(MyTree*)child; + +- (int)numberOfChildren; +- (NSArray*)children; +- (MyTree*)firstChild; +- (MyTree*)lastChild; +- (MyTree*)childAtIndex:(int)index; + +@end diff --git a/macosx/MyTree.m b/macosx/MyTree.m new file mode 100644 index 00000000..ddbd4258 --- /dev/null +++ b/macosx/MyTree.m @@ -0,0 +1,279 @@ +// +// MyTree.m +// celestia +// +// Created by Bob Ippolito on Thu Jun 20 2002. +// Copyright (c) 2002 Chris Laurel. All rights reserved. +// + +#import "MyTree.h" +#import +@implementation MyVector +-(id)init +{ + self = [super init]; + _array = [[NSMutableArray arrayWithCapacity:0] retain]; + _myClass = [NSObject class]; + return self; +} +-(id)initWithClass:(Class)myClass +{ + self = [self init]; + _myClass = myClass; + return self; +} +-(void)addObject:(id)obj +{ + if (![obj isKindOfClass:_myClass]) + [NSException raise:@"TypeError" format:@"%s invalid, only %s allowed",NAMEOF(obj),_myClass->name]; + [_array addObject:obj]; +} +-(void)insertObject:(id)obj atIndex:(unsigned)idx +{ + if (![obj isKindOfClass:_myClass]) + [NSException raise:@"TypeError" format:@"%s invalid, only %s allowed",NAMEOF(obj),_myClass->name]; + [_array insertObject:obj atIndex:idx]; +} +-(void)removeLastObject +{ + [_array removeLastObject]; +} +-(void)removeObjectAtIndex:(unsigned)idx +{ + [_array removeObjectAtIndex:idx]; +} +-(void)replaceObjectAtIndex:(unsigned)idx withObject:(id)obj +{ + if (![obj isKindOfClass:_myClass]) + [NSException raise:@"TypeError" format:@"%s invalid, only %s allowed",NAMEOF(obj),_myClass->name]; + [_array replaceObjectAtIndex:idx withObject:obj]; +} +-(unsigned)count +{ + return [_array count]; +} +-(id)objectAtIndex:(unsigned)idx +{ + return [_array objectAtIndex:idx]; +} +@end + +@implementation MyTree +-(id)init +{ + self = [super init]; + _nodeValue = nil; + _children = nil; + _parent = nil; + return self; +} +-(void)dealloc +{ + NSLog(@"[MyTree dealloc]"); + NSLog(@"%@",self); + if ([self nodeValue] != nil) + [[self nodeValue] autorelease]; + if ([self children] != nil) + [[self children] autorelease]; + _nodeValue = nil; + _children = nil; + _parent = nil; + [super dealloc]; +} +-(id)initWithNode:(id)obj parent:(MyTree*)parent +{ + self = [self init]; + _nodeValue = [obj retain]; + _parent = parent; + _children = nil; + return self; +} +-(id)initWithNode:(id)obj parent:(MyTree*)parent children:(NSArray*)children +{ + NSEnumerator* enumerator; + self = [self initWithNode:obj parent:parent]; + _children = [[MyVector alloc] initWithClass:[MyTree class]]; + enumerator = [children objectEnumerator]; + while ((obj = [enumerator nextObject]) != nil) + [_children addObject:obj]; + return self; +} +-(id)initWithDictionary:(NSDictionary*)dict parent:(MyTree*)parent +{ + NSMutableArray* children = nil; + NSArray* origArray = nil; + NSEnumerator* enumerator = nil; + NSDictionary* childDict = nil; + id nodeValue = nil; + nodeValue = [dict objectForKey:@"nodeValue"]; + // Leaf + if ((origArray = [dict objectForKey:@"children"]) == nil) + return [self initWithNode:nodeValue parent:parent]; + children = [[MyVector alloc] initWithClass:[MyTree class]]; + enumerator = [origArray objectEnumerator]; + while ((childDict = [enumerator nextObject]) != nil) + [children addObject:[[[MyTree alloc] initWithDictionary:childDict parent:self] autorelease]]; + return [self initWithNode:nodeValue parent:parent children:children]; +} +-(MyTree*)parent +{ + return _parent; +} +-(MyVector*)children +{ + return _children; +} +-(id)nodeValue +{ + return _nodeValue; +} +-(BOOL)isLeaf +{ + return (([self children] == nil) ? YES : NO); +} +-(void)setNode:(id)obj +{ + if ([self nodeValue] != nil) + [[self nodeValue] autorelease]; + _nodeValue = [obj retain]; +} +-(void)setParent:(id)obj +{ + _parent = obj; +} +-(void)setChildren:(NSArray*)children +{ + NSEnumerator *enumerator = nil; + id obj = nil; + if ([self children] == nil) + [[self children] autorelease]; + if (children == nil) { + _children = nil; + return; + } + enumerator = [children objectEnumerator]; + _children = [[MyVector alloc] initWithClass:[MyTree class]]; + while ((obj = [enumerator nextObject]) != nil) + [_children addObject:obj]; +} +-(NSDictionary*)dictionary +{ + return [NSDictionary dictionaryWithObjectsAndKeys:[self nodeValue],@"nodeValue",[NSNumber numberWithBool:[self isLeaf]],@"isLeaf",[self children],@"children",nil,nil]; +} +-(NSDictionary*)recursiveDictionary +{ + NSMutableArray* array; + NSEnumerator* enumerator; + MyTree* obj; + if ([self isLeaf]) + return [self dictionary]; + enumerator = [[self children] objectEnumerator]; + array = [NSMutableArray arrayWithCapacity:[[self children] count]]; + while ((obj = [enumerator nextObject]) != nil) + [array addObject:[obj recursiveDictionary]]; + return [NSDictionary dictionaryWithObjectsAndKeys:_nodeValue,@"nodeValue",array,@"children",nil,nil]; +} +-(NSString*)description +{ + return [[self dictionary] description]; +} +-(BOOL)isDescendantOfNode:(MyTree*)node +{ + MyTree* parent = self; + if ([self isEqualTo:node]) + return YES; + while ((parent = [parent parent]) != nil) + if ([node isEqualTo:parent]) + return YES; + return NO; +} +-(BOOL)isDescendantOfNodeInArray:(NSArray*)array +{ + NSEnumerator* enumerator = [array objectEnumerator]; + MyTree* node = nil; + while ((node = [enumerator nextObject]) != nil) + if ([self isDescendantOfNode:node] == YES) + return YES; + return NO; +} + +- (void)insertChild:(MyTree*)child atIndex:(int)index { + [[self children] insertObject:child atIndex:index]; + [child setParent: self]; +} + +- (void)insertChildren:(NSArray*)children atIndex:(int)index { + [[self children] insertObjectsFromArray: children atIndex: index]; + [children makeObjectsPerformSelector:@selector(setParent:) withObject:self]; +} + +- (void)_removeChildrenIdenticalTo:(NSArray*)children { + MyTree *child; + NSEnumerator *childEnumerator = [children objectEnumerator]; + [children makeObjectsPerformSelector:@selector(setParent:) withObject:nil]; + while ((child = [childEnumerator nextObject]) != nil) { + [[self children] removeObjectIdenticalTo:child]; + } +} + +- (void)removeChild:(MyTree*)child { + [[self children] removeObject:child]; +/* + int index = [self indexOfChild: child]; + if (index != NSNotFound) { + [self _removeChildrenIdenticalTo: [NSArray arrayWithObject: [self childAtIndex:index]]]; + } +*/ +} + +- (void)removeFromParent { + [[self parent] removeChild:self]; +} + +- (int)indexOfChild:(MyTree*)child { + return [[self children] indexOfObject:child]; +} + +- (int)indexOfChildIdenticalTo:(MyTree*)child { + return [[self children] indexOfObjectIdenticalTo:child]; +} + +- (int)numberOfChildren { + return [[self children] count]; +} + +- (MyTree*)firstChild { + return [[self children] objectAtIndex:0]; +} + +- (MyTree*)lastChild { + return [[self children] lastObject]; +} + +- (MyTree*)childAtIndex:(int)index { + return [[self children] objectAtIndex:index]; +} + +// Returns the minimum nodes from 'allNodes' required to cover the nodes in 'allNodes'. +// This methods returns an array containing nodes from 'allNodes' such that no node in +// the returned array has an ancestor in the returned array. + +// There are better ways to compute this, but this implementation should be efficient for our app. ++ (NSArray *) minimumNodeCoverFromNodesInArray: (NSArray *)allNodes { + NSMutableArray *minimumCover = [NSMutableArray array]; + NSMutableArray *nodeQueue = [NSMutableArray arrayWithArray:allNodes]; + MyTree *node = nil; + while ([nodeQueue count]) { + node = [nodeQueue objectAtIndex:0]; + [nodeQueue removeObjectAtIndex:0]; + while ( [node parent] && [nodeQueue containsObjectIdenticalTo:[node parent]] ) { + [nodeQueue removeObjectIdenticalTo: node]; + node = [node parent]; + } + if (![node isDescendantOfNodeInArray: minimumCover]) [minimumCover addObject: node]; + [nodeQueue removeObjectIdenticalTo: node]; + } + return minimumCover; +} + +@end \ No newline at end of file diff --git a/macosx/celestia.pbproj/project.pbxproj b/macosx/celestia.pbproj/project.pbxproj index 9878dbb8..b2b5e24d 100644 --- a/macosx/celestia.pbproj/project.pbxproj +++ b/macosx/celestia.pbproj/project.pbxproj @@ -14,6 +14,7 @@ 080E96DDFE201D6D7F000001 = { children = ( F5040B0F02A484DA014901DC, + F5231C7102C2997601000006, F5274ED302AE88260100020A, F57F9FD402B94A0B01000006, F57FA4F002B9AB8601000006, @@ -21,6 +22,7 @@ F55C817602AF55890100020A, F57F9FD302B94A0B01000006, F5040B0E02A484DA014901DC, + F5231C7202C2997601000006, F5274ED202AE88260100020A, F57FA4EF02B9AB8601000006, F578B7B302B3E4DB0100020A, @@ -407,6 +409,9 @@ F578B7B502B3E4DB0100020A, F57F9FD502B94A0B01000006, F57FA4F102B9AB8601000006, + F5231C7402C2997601000006, + F56FFFAB02C571280100020A, + F56FFFB002C578050100020A, ); isa = PBXHeadersBuildPhase; }; @@ -515,6 +520,9 @@ F59DDEAA02B5F10E0100020A, F57F9FD602B94A0B01000006, F57FA4F202B9AB8601000006, + F5231C7302C2997601000006, + F56FFFAC02C571280100020A, + F56FFFAF02C578050100020A, ); isa = PBXSourcesBuildPhase; }; @@ -843,6 +851,7 @@ F51C6DB602959A17014901DC, F51C6DB702959A17014901DC, F51C6DB802959A17014901DC, + F56FFFAD02C578050100020A, F51C6DB902959A17014901DC, F51C6DBA02959A17014901DC, F51C6DBB02959A17014901DC, @@ -887,6 +896,7 @@ F51C6DE202959A17014901DC, F51C6DE302959A17014901DC, F51C6DE402959A17014901DC, + F56FFFAE02C578050100020A, F51C6DE502959A17014901DC, F51C6DE602959A17014901DC, F51C6DE702959A17014901DC, @@ -2269,6 +2279,28 @@ settings = { }; }; + F5231C7102C2997601000006 = { + isa = PBXFileReference; + path = CelestiaFavorites.m; + refType = 4; + }; + F5231C7202C2997601000006 = { + isa = PBXFileReference; + path = CelestiaFavorites.h; + refType = 4; + }; + F5231C7302C2997601000006 = { + fileRef = F5231C7102C2997601000006; + isa = PBXBuildFile; + settings = { + }; + }; + F5231C7402C2997601000006 = { + fileRef = F5231C7202C2997601000006; + isa = PBXBuildFile; + settings = { + }; + }; F5274ED202AE88260100020A = { isa = PBXFileReference; path = CelestiaOpenGLView.h; @@ -2903,13 +2935,61 @@ settings = { }; }; + F56FFFA902C571280100020A = { + isa = PBXFileReference; + path = MyTree.h; + refType = 4; + }; + F56FFFAA02C571280100020A = { + isa = PBXFileReference; + path = MyTree.m; + refType = 4; + }; + F56FFFAB02C571280100020A = { + fileRef = F56FFFA902C571280100020A; + isa = PBXBuildFile; + settings = { + }; + }; + F56FFFAC02C571280100020A = { + fileRef = F56FFFAA02C571280100020A; + isa = PBXBuildFile; + settings = { + }; + }; + F56FFFAD02C578050100020A = { + isa = PBXFileReference; + name = boundaries.cpp; + path = /Users/bob/src/celestia/src/celengine/boundaries.cpp; + refType = 0; + }; + F56FFFAE02C578050100020A = { + isa = PBXFileReference; + name = boundaries.h; + path = /Users/bob/src/celestia/src/celengine/boundaries.h; + refType = 0; + }; + F56FFFAF02C578050100020A = { + fileRef = F56FFFAD02C578050100020A; + isa = PBXBuildFile; + settings = { + }; + }; + F56FFFB002C578050100020A = { + fileRef = F56FFFAE02C578050100020A; + isa = PBXBuildFile; + settings = { + }; + }; F578B79D02B3E2AD0100020A = { children = ( F578B79E02B3E2DD0100020A, + F56FFFAA02C571280100020A, F578B7A102B3E2DD0100020A, F578B7A002B3E2DD0100020A, F55F041E02B152180100020A, F578B7A202B3E2DD0100020A, + F56FFFA902C571280100020A, F578B7A302B3E2DD0100020A, F578B79F02B3E2DD0100020A, F55F041D02B152180100020A,