Major changes to the favorites system. Menus and outline view should work pretty much as expected now, except that it does not save because it's been disentangled from the STL vector implementation and I haven't written the serialization code yet, but it will be pretty easy. Uses a tree implementation, unlimited folder depth, no problems with multiple folders at the same level with the same name.

Added boundaries.cpp/h to the pbproj.

Changes don't touch any non-OSX portions of the codebase.
ver1_5_1
Bob Ippolito 2002-06-23 04:40:07 +00:00
parent 2dab8ba391
commit 93ac6a696a
18 changed files with 737 additions and 442 deletions

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -9,11 +9,18 @@
#import <Foundation/Foundation.h>
#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

View File

@ -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<void*>(&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<void*>(&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<FavoritesList*>([_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;i<end;++i) {
if (![folderName isEqualToString:[[self objectAtIndex:i] parentFolder]]) {
break;
}
}
return i;
}
-(unsigned)numberOfChildrenOfItem:(CelestiaFavorite*)folder
{
/* FIXME, needs to step over children folders */
unsigned first,last;
if (folder == nil)
return [self count];
if (![folder isFolder])
return 0;
first = [self firstIndexWithParentFolder:folder];
last = [self lastIndexWithParentFolder:folder];
if ((last == NSNotFound) || (first == NSNotFound))
return 0;
return last-first;
}
-(void)addNewFavorite:(NSString*)name withParentFolder:(CelestiaFavorite*)folder atIndex:(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];
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 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

View File

@ -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

View File

@ -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 <Foundation/Foundation.h>
#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

View File

@ -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:@"<CelestiaFavorites numberOfChildren=%d>",[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

View File

@ -1,6 +1,7 @@
/* ContextOutlineView */
#import <Cocoa/Cocoa.h>
#import "NSOutlineView_Extensions.h"
@interface ContextOutlineView : NSOutlineView {
}

View File

@ -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;

View File

@ -3,7 +3,7 @@
<plist version="0.9">
<dict>
<key>IBDocumentLocation</key>
<string>45 242 515 457 0 0 1152 746 </string>
<string>66 156 515 457 0 0 1152 746 </string>
<key>IBEditorPositions</key>
<dict>
<key>242</key>
@ -11,7 +11,7 @@
<key>29</key>
<string>19 661 452 44 0 0 1152 746 </string>
<key>296</key>
<string>491 337 170 341 0 0 1152 746 </string>
<string>491 338 170 341 0 0 1152 746 </string>
<key>335</key>
<string>522 588 98 114 0 0 1152 746 </string>
<key>342</key>
@ -25,11 +25,9 @@
</array>
<key>IBOpenObjects</key>
<array>
<integer>242</integer>
<integer>296</integer>
<integer>352</integer>
<integer>21</integer>
</array>
<key>IBSystem Version</key>
<string>5S60</string>
<string>5S66</string>
</dict>
</plist>

Binary file not shown.

View File

@ -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

View File

@ -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 <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)childIndex;
-(void)_performDropOperation:(id <NSDraggingInfo>)info onNode:(TreeNode*)parentNode atIndex:(int)childIndex;
-(void)_performDropOperation:(id <NSDraggingInfo>)info onNode:(id)pnode atIndex:(int)childIndex;
-(BOOL)outlineView:(NSOutlineView*)olv acceptDrop:(id <NSDraggingInfo>)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

View File

@ -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 <NSDraggingInfo>)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 <NSDraggingInfo>)info onNode:(TreeNode*)parentNode atIndex:(int)childIndex {
- (void)_performDropOperation:(id <NSDraggingInfo>)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]<childIndex) childIndex--;
[_draggedNodeParent removeChild: _draggedNode];
}
[parentNode insertChildren: _draggedNodes atIndex: childIndex];
}
else if ([pboard availableTypeFromArray:[NSArray arrayWithObject: NSStringPboardType]]) {
NSString *string = [pboard stringForType: NSStringPboardType];
SimpleTreeNode *newItem = [SimpleTreeNode treeNodeWithData: [SimpleNodeData leafDataWithName:string]];
itemsToSelect = [NSMutableArray arrayWithObject: newItem];
[parentNode insertChild: newItem atIndex:childIndex++];
}
[outlineView reloadData];
[[CelestiaFavorites sharedFavorites] synchronize];
[outlineView selectItems: itemsToSelect byExtendingSelection: NO];
}
- (BOOL)outlineView:(NSOutlineView*)olv acceptDrop:(id <NSDraggingInfo>)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

62
macosx/MyTree.h 100644
View File

@ -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 <Foundation/Foundation.h>
#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

279
macosx/MyTree.m 100644
View File

@ -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 <objc/objc-class.h>
@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

View File

@ -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,