SourceForge: timemon/timemon: changeset 188:843e8884cfcf
Rename DragController to TMProjectDragController 1of2
authorFrank <wixardy@ceresalto.ca>
Mon Sep 28 21:51:03 2009 -0400 (8 weeks ago)
changeset 188843e8884cfcf
parent 1878204198ca120
child 1895db54346d8d8
Rename DragController to TMProjectDragController 1of2
DragController.h
DragController.m
English.lproj/MainMenu.xib
Japanese.lproj/MainMenu.xib
TMProjectDragController.h
TMProjectDragController.m
TimeMon.xcodeproj/project.pbxproj
     1.1 --- a/DragController.h	Sat Sep 26 22:05:44 2009 -0400
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,25 +0,0 @@
     1.4 -/* TimeMon
     1.5 -Copyright (C) 2009 Ceresalto
     1.6 -
     1.7 -This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
     1.8 -as published by the Free Software Foundation; version 2 of the License.
     1.9 -
    1.10 -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    1.11 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
    1.12 -
    1.13 -You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
    1.14 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
    1.15 -
    1.16 -@interface DragController : NSObject{
    1.17 -	IBOutlet NSTreeController *groupTreeControl;
    1.18 -	IBOutlet NSOutlineView *treeTable;
    1.19 -
    1.20 -	NSArray *dragType;
    1.21 -	NSTreeNode *draggedNode;
    1.22 -}
    1.23 -
    1.24 -- (BOOL)category:(NSManagedObject *)cat isSubCategoryOf:(NSManagedObject * )possibleSub;
    1.25 -- (void)resortGroups:(NSManagedObjectContext *)objectContext forParent:(NSManagedObject *)parent;
    1.26 -- (NSArray *)getSubGroups:(NSManagedObjectContext *)objectContext forParent:(NSManagedObject *)parent;
    1.27 -
    1.28 -@end
     2.1 --- a/DragController.m	Sat Sep 26 22:05:44 2009 -0400
     2.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.3 @@ -1,268 +0,0 @@
     2.4 -/* TimeMon
     2.5 -Copyright (C) 2009 Ceresalto
     2.6 -
     2.7 -This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
     2.8 -as published by the Free Software Foundation; version 2 of the License.
     2.9 -
    2.10 -This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.11 -MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
    2.12 -
    2.13 -You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
    2.14 -Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
    2.15 -
    2.16 -#import "DragController.h"
    2.17 -#import "NSTreeController_Extensions.h"
    2.18 -#import "CWCommonUtils.h"
    2.19 -
    2.20 -
    2.21 -@implementation DragController
    2.22 -- (void)awakeFromNib {
    2.23 -	dragType = [NSArray arrayWithObjects:@"factorialDragType", nil];
    2.24 -	[dragType retain];
    2.25 -	
    2.26 -	[groupTreeControl setSelectsInsertedObjects:YES];
    2.27 -	[treeTable registerForDraggedTypes:dragType];
    2.28 -	
    2.29 -	NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:@"position" ascending:YES];
    2.30 -	[groupTreeControl setSortDescriptors:[NSArray arrayWithObject: sortDesc]];
    2.31 -	[sortDesc release];
    2.32 -
    2.33 -	[[NSNotificationCenter defaultCenter] addObserver:self
    2.34 -											selector:@selector(startEditing:)
    2.35 -												name:@"TMNewProjectAdded"
    2.36 -											  object:nil];
    2.37 -	[[NSNotificationCenter defaultCenter] addObserver:self
    2.38 -											selector:@selector(sortObjects:)
    2.39 -												name:@"TMProjectsNeedResort"
    2.40 -											  object:nil];
    2.41 -	[[NSNotificationCenter defaultCenter] addObserver:self
    2.42 -											 selector:@selector(outlineViewItemDidExpand:)
    2.43 -												 name:@"NSOutlineViewItemDidExpandNotification"
    2.44 -											   object:nil];
    2.45 -	[[NSNotificationCenter defaultCenter] addObserver:self
    2.46 -											 selector:@selector(outlineViewItemDidCollapse:)
    2.47 -												 name:@"NSOutlineViewItemDidCollapseNotification"
    2.48 -											   object:nil];
    2.49 -}
    2.50 -
    2.51 -- (void)sortObjects:(NSNotification *)aNote{
    2.52 -	if (!IsEmpty(groupTreeControl.content)){
    2.53 -		[self resortGroups:[[groupTreeControl.content objectAtIndex:0] managedObjectContext] forParent:nil];
    2.54 -		[groupTreeControl rearrangeObjects];
    2.55 -	}
    2.56 -}
    2.57 -
    2.58 -- (void)startEditing:(NSNotification *)aNote{
    2.59 -	NSTreeNode *selectedNode;
    2.60 -	if (!IsEmpty(groupTreeControl.selectedNodes)){
    2.61 -		selectedNode = [groupTreeControl.selectedNodes objectAtIndex:0];
    2.62 -		
    2.63 -		//add some missing values
    2.64 -		[aNote.object setValue:[NSNumber numberWithInt:[[[selectedNode representedObject] valueForKey:@"position"] intValue]+1] forKey:@"position"];
    2.65 -		[aNote.object setValue:[[selectedNode representedObject] valueForKey:@"parent"] forKey:@"parent"];
    2.66 -	}
    2.67 -	else
    2.68 -		[aNote.object setValue:[NSNumber numberWithInt:-1] forKey:@"position"];
    2.69 -	
    2.70 -	//resort
    2.71 -	[self sortObjects:nil];
    2.72 -	
    2.73 -	//select the new object and start editing it
    2.74 -	NSTreeNode *node = [groupTreeControl treeNodeForObject:[[NSTreeNode treeNodeWithRepresentedObject:aNote.object] representedObject]];
    2.75 -	[groupTreeControl setSelectionIndexPath:node.indexPath];
    2.76 -	[treeTable editColumn:0 row:treeTable.selectedRow withEvent:nil select:YES];
    2.77 -	
    2.78 -	//undo registration; create a group for the insert and the name change
    2.79 -	[treeTable.undoManager beginUndoGrouping];
    2.80 -}
    2.81 -
    2.82 -//---------------------------------------------------------------------------
    2.83 -#pragma mark NSOutlineView datasource methods -- see NSOutlineViewDataSource
    2.84 -//---------------------------------------------------------------------------
    2.85 -- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard{
    2.86 -	[pboard declareTypes:dragType owner:self];
    2.87 -	// items is an array of NSTreeControllerTreeNodes
    2.88 -	draggedNode = [items objectAtIndex:0];
    2.89 -
    2.90 -	return YES;
    2.91 -}
    2.92 -
    2.93 -- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index{
    2.94 -	NSTreeNode *parentNode = item;
    2.95 -	NSTreeNode *siblingNode;
    2.96 -	NSTreeNode *proxy = groupTreeControl.arrangedObjects;
    2.97 -	NSManagedObject *draggedGroup = [draggedNode representedObject];
    2.98 -
    2.99 -	BOOL draggingDown = NO;
   2.100 -	BOOL isRootLevelDrag = NO;
   2.101 -
   2.102 -	// -------------------------
   2.103 -	// Setup comparison paths
   2.104 -	// -------------------------
   2.105 -	NSIndexPath *draggedPath = draggedNode.indexPath;
   2.106 -	NSIndexPath *siblingPath = [NSIndexPath indexPathWithIndex:index];
   2.107 -	if (!parentNode)
   2.108 -		isRootLevelDrag = YES;
   2.109 -	else
   2.110 -		// A non-root drag - the index value is relative to this parent's children
   2.111 -		siblingPath = [parentNode.indexPath indexPathByAddingIndex:index];
   2.112 -	
   2.113 -	// -----------------------------------------------------------------------------
   2.114 -	// Compare paths - modify sibling path for down drags, exit for redundant drags
   2.115 -	// -----------------------------------------------------------------------------
   2.116 -	switch ([draggedPath compare:siblingPath]){
   2.117 -		case NSOrderedAscending:  // reset path for down dragging
   2.118 -			if (isRootLevelDrag)
   2.119 -				siblingPath = [NSIndexPath indexPathWithIndex:index - 1];
   2.120 -			else
   2.121 -				siblingPath = [parentNode.indexPath indexPathByAddingIndex:index - 1];
   2.122 -			
   2.123 -			draggingDown = YES;
   2.124 -			break;
   2.125 -
   2.126 -		case NSOrderedSame:
   2.127 -			return NO;
   2.128 -			break;
   2.129 -	}
   2.130 -	
   2.131 -	siblingNode = [proxy descendantNodeAtIndexPath:siblingPath];
   2.132 -
   2.133 -	// ------------------------------------------------------------
   2.134 -	// SPECIAL CASE: Dragging to the bottom
   2.135 -	// ------------------------------------------------------------
   2.136 -	// - K                 - K              - C         - C
   2.137 -	// - - U               - - C     OR     - U         - F
   2.138 -	// - - C     ====>     - - F            - F         - K
   2.139 -	// - - F               - U              - K         - U
   2.140 -	// ------------------------------------------------------------
   2.141 -	if (isRootLevelDrag  && !siblingNode){
   2.142 -		draggingDown = YES;
   2.143 -		siblingPath = [NSIndexPath indexPathWithIndex:proxy.childNodes.count - 1];
   2.144 -		siblingNode = [proxy descendantNodeAtIndexPath:siblingPath];
   2.145 -	}
   2.146 -	
   2.147 -	// ------------------------------------------------------------
   2.148 -	// Give the dragged item a postion relative to it's new sibling
   2.149 -	// ------------------------------------------------------------
   2.150 -	NSManagedObject *sibling = [siblingNode representedObject];
   2.151 -	NSNumber *bystanderPosition = [sibling valueForKey:@"position"];
   2.152 -	int newPos = (draggingDown ? [bystanderPosition intValue] + 1 : [bystanderPosition intValue] - 1);
   2.153 -	[draggedGroup setValue:[NSNumber numberWithInt:newPos] forKey:@"position"];
   2.154 -	
   2.155 -	// ----------------------------------------------------------------------------------------------
   2.156 -	// Set the new parent for the dragged item, resort the position attributes and refresh the tree
   2.157 -	// ----------------------------------------------------------------------------------------------
   2.158 -	
   2.159 -	[draggedGroup setValue:[parentNode representedObject] forKey:@"parent"];
   2.160 -	
   2.161 -	[self resortGroups:[draggedGroup managedObjectContext] forParent:[parentNode representedObject]];
   2.162 -	[groupTreeControl rearrangeObjects];
   2.163 -	
   2.164 -	return YES;
   2.165 -}
   2.166 -
   2.167 -- (NSArray *)getSubGroups:(NSManagedObjectContext *)objectContext forParent:(NSManagedObject *)parent{
   2.168 -	NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
   2.169 -	NSEntityDescription *entity = [NSEntityDescription entityForName:@"projects" inManagedObjectContext:objectContext];
   2.170 -
   2.171 -	[request setEntity:entity];
   2.172 -	NSSortDescriptor *aSortDesc = [[NSSortDescriptor alloc] initWithKey:@"position" ascending:YES];
   2.173 -	[request setSortDescriptors:[NSArray arrayWithObject: aSortDesc]];
   2.174 -	[aSortDesc release];
   2.175 -
   2.176 -	NSPredicate *validationPredicate = [NSPredicate predicateWithFormat:@"parent == %@", parent];
   2.177 -
   2.178 -	[request setPredicate:validationPredicate];
   2.179 -
   2.180 -	NSError *error = nil;  // TODO - check the error bozo
   2.181 -	return [objectContext executeFetchRequest:request error:&error];
   2.182 -}
   2.183 -
   2.184 -- (void)resortGroups:(NSManagedObjectContext *)objectContext forParent:(NSManagedObject *)parent{
   2.185 -	NSArray *array = [self getSubGroups:objectContext forParent:parent];
   2.186 -
   2.187 -	// Reset the indexes...
   2.188 -	NSManagedObject *anObject;
   2.189 -	int index = 0;
   2.190 -	for (anObject in array){
   2.191 -		// Multiply index by 10 to make dragging code easier to implement ;) ....
   2.192 -		[anObject setValue:[NSNumber numberWithInt:(index * 10)] forKey:@"position"];
   2.193 -		index++;
   2.194 -	}
   2.195 -}
   2.196 -
   2.197 -- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index{
   2.198 -	NSTreeNode *newParent = item;
   2.199 -
   2.200 -	// drags to the root are always acceptable
   2.201 -	if (!newParent)
   2.202 -		return NSDragOperationGeneric;
   2.203 -
   2.204 -	// Verify that we are not dragging a parent to one of it's ancestors
   2.205 -	// causes a parent loop where a group of nodes point to each other and disappear
   2.206 -	// from the control
   2.207 -	NSManagedObject *dragged = [draggedNode representedObject];
   2.208 -	NSManagedObject *newP = [newParent representedObject];
   2.209 -
   2.210 -	if ([self category:dragged isSubCategoryOf:newP])
   2.211 -		return NO;
   2.212 -	
   2.213 -	return NSDragOperationGeneric;
   2.214 -}
   2.215 -
   2.216 -- (BOOL)category:(NSManagedObject *)cat isSubCategoryOf:(NSManagedObject *)possibleSub{
   2.217 -	// Depends on your interpretation of subCategory ....
   2.218 -	if (cat == possibleSub)
   2.219 -		return YES;
   2.220 -
   2.221 -	NSManagedObject *possSubParent = [possibleSub valueForKey:@"parent"];
   2.222 -
   2.223 -	if (!possSubParent)
   2.224 -		return NO;
   2.225 -
   2.226 -	while (possSubParent){
   2.227 -		if (possSubParent == cat)
   2.228 -			return YES;
   2.229 -		// move up the tree
   2.230 -		possSubParent = [possSubParent valueForKey:@"parent"];
   2.231 -	}
   2.232 -	
   2.233 -	return NO;
   2.234 -}
   2.235 -
   2.236 -- (BOOL)canRemove
   2.237 -{
   2.238 -	return treeTable.selectedRow >= 0;
   2.239 -}
   2.240 -
   2.241 -/*
   2.242 -The following are implemented as stubs because they are required when
   2.243 - implementing an NSOutlineViewDataSource. Because we use bindings on the
   2.244 - table column these methods are never called. The NSLog statements have been
   2.245 - included to prove that these methods are not called.
   2.246 - */
   2.247 -- (int)outlineView:(NSOutlineView *)ov numberOfChildrenOfItem:(id)item{
   2.248 -	return 0;
   2.249 -}
   2.250 -
   2.251 -- (BOOL)outlineView:(NSOutlineView *)ov isItemExpandable:(id)item{
   2.252 -	return NO;
   2.253 -}
   2.254 -
   2.255 -- (id)outlineView:(NSOutlineView *)ov child:(int)index ofItem:(id)item{
   2.256 -	return nil;
   2.257 -}
   2.258 -
   2.259 -- (id)outlineView:(NSOutlineView *)ov objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item{
   2.260 -	return nil;
   2.261 -}
   2.262 -
   2.263 -- (void)outlineViewItemDidExpand:(NSNotification *)notification{
   2.264 -	[[[notification.userInfo valueForKey:@"NSObject"] representedObject] setValue:[NSNumber numberWithBool:YES] forKey:@"expandedState"];
   2.265 -}
   2.266 -
   2.267 -- (void)outlineViewItemDidCollapse:(NSNotification *)notification{
   2.268 -	[[[notification.userInfo valueForKey:@"NSObject"] representedObject] setValue:[NSNumber numberWithBool:NO] forKey:@"expandedState"];
   2.269 -}
   2.270 -
   2.271 -@end
     3.1 --- a/English.lproj/MainMenu.xib	Sat Sep 26 22:05:44 2009 -0400
     3.2 +++ b/English.lproj/MainMenu.xib	Mon Sep 28 21:51:03 2009 -0400
     3.3 @@ -2,14 +2,12 @@
     3.4  <archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
     3.5  	<data>
     3.6  		<int key="IBDocument.SystemTarget">1050</int>
     3.7 -		<string key="IBDocument.SystemVersion">9J61</string>
     3.8 +		<string key="IBDocument.SystemVersion">9L30</string>
     3.9  		<string key="IBDocument.InterfaceBuilderVersion">677</string>
    3.10 -		<string key="IBDocument.AppKitVersion">949.46</string>
    3.11 +		<string key="IBDocument.AppKitVersion">949.54</string>
    3.12  		<string key="IBDocument.HIToolboxVersion">353.00</string>
    3.13  		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
    3.14  			<bool key="EncodedWithXMLCoder">YES</bool>
    3.15 -			<integer value="29"/>
    3.16 -			<integer value="424"/>
    3.17  		</object>
    3.18  		<object class="NSArray" key="IBDocument.PluginDependencies">
    3.19  			<bool key="EncodedWithXMLCoder">YES</bool>
    3.20 @@ -742,7 +740,7 @@
    3.21  				<string key="NSWindowContentMaxSize">{3.40282e+38, 3.40282e+38}</string>
    3.22  				<string key="NSWindowContentMinSize">{422, 216}</string>
    3.23  				<object class="NSView" key="NSWindowView" id="885368816">
    3.24 -					<reference key="NSNextResponder"/>
    3.25 +					<nil key="NSNextResponder"/>
    3.26  					<int key="NSvFlags">256</int>
    3.27  					<object class="NSMutableArray" key="NSSubviews">
    3.28  						<bool key="EncodedWithXMLCoder">YES</bool>
    3.29 @@ -1411,7 +1409,6 @@
    3.30  						</object>
    3.31  					</object>
    3.32  					<string key="NSFrameSize">{662, 275}</string>
    3.33 -					<reference key="NSSuperview"/>
    3.34  				</object>
    3.35  				<string key="NSScreenRect">{{0, 0}, {1680, 1028}}</string>
    3.36  				<string key="NSMinSize">{422, 238}</string>
    3.37 @@ -1422,7 +1419,7 @@
    3.38  				<string key="NSClassName">SUUpdater</string>
    3.39  			</object>
    3.40  			<object class="NSCustomObject" id="339013080">
    3.41 -				<string key="NSClassName">DragController</string>
    3.42 +				<string key="NSClassName">TMProjectDragController</string>
    3.43  			</object>
    3.44  			<object class="NSArrayController" id="473299187">
    3.45  				<object class="NSMutableArray" key="NSDeclaredKeys">
    3.46 @@ -3756,35 +3753,6 @@
    3.47  			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
    3.48  				<bool key="EncodedWithXMLCoder">YES</bool>
    3.49  				<object class="IBPartialClassDescription">
    3.50 -					<string key="className">DragController</string>
    3.51 -					<string key="superclassName">NSObject</string>
    3.52 -					<object class="NSMutableDictionary" key="outlets">
    3.53 -						<bool key="EncodedWithXMLCoder">YES</bool>
    3.54 -						<object class="NSMutableArray" key="dict.sortedKeys">
    3.55 -							<bool key="EncodedWithXMLCoder">YES</bool>
    3.56 -							<string>groupTreeControl</string>
    3.57 -							<string>treeTable</string>
    3.58 -						</object>
    3.59 -						<object class="NSMutableArray" key="dict.values">
    3.60 -							<bool key="EncodedWithXMLCoder">YES</bool>
    3.61 -							<string>NSTreeController</string>
    3.62 -							<string>NSOutlineView</string>
    3.63 -						</object>
    3.64 -					</object>
    3.65 -					<object class="IBClassDescriptionSource" key="sourceIdentifier">
    3.66 -						<string key="majorKey">IBProjectSource</string>
    3.67 -						<string key="minorKey">DragController.h</string>
    3.68 -					</object>
    3.69 -				</object>
    3.70 -				<object class="IBPartialClassDescription">
    3.71 -					<string key="className">DragController</string>
    3.72 -					<string key="superclassName">NSObject</string>
    3.73 -					<object class="IBClassDescriptionSource" key="sourceIdentifier">
    3.74 -						<string key="majorKey">IBUserSource</string>
    3.75 -						<string key="minorKey"/>
    3.76 -					</object>
    3.77 -				</object>
    3.78 -				<object class="IBPartialClassDescription">
    3.79  					<string key="className">FirstResponder</string>
    3.80  					<string key="superclassName">NSObject</string>
    3.81  					<object class="IBClassDescriptionSource" key="sourceIdentifier">
    3.82 @@ -3862,6 +3830,27 @@
    3.83  					</object>
    3.84  				</object>
    3.85  				<object class="IBPartialClassDescription">
    3.86 +					<string key="className">TMProjectDragController</string>
    3.87 +					<string key="superclassName">NSObject</string>
    3.88 +					<object class="NSMutableDictionary" key="outlets">
    3.89 +						<bool key="EncodedWithXMLCoder">YES</bool>
    3.90 +						<object class="NSMutableArray" key="dict.sortedKeys">
    3.91 +							<bool key="EncodedWithXMLCoder">YES</bool>
    3.92 +							<string>groupTreeControl</string>
    3.93 +							<string>treeTable</string>
    3.94 +						</object>
    3.95 +						<object class="NSMutableArray" key="dict.values">
    3.96 +							<bool key="EncodedWithXMLCoder">YES</bool>
    3.97 +							<string>NSTreeController</string>
    3.98 +							<string>NSOutlineView</string>
    3.99 +						</object>
   3.100 +					</object>
   3.101 +					<object class="IBClassDescriptionSource" key="sourceIdentifier">
   3.102 +						<string key="majorKey">IBUserSource</string>
   3.103 +						<string key="minorKey"/>
   3.104 +					</object>
   3.105 +				</object>
   3.106 +				<object class="IBPartialClassDescription">
   3.107  					<string key="className">TMTableView</string>
   3.108  					<string key="superclassName">NSTableView</string>
   3.109  					<object class="IBClassDescriptionSource" key="sourceIdentifier">
     4.1 --- a/Japanese.lproj/MainMenu.xib	Sat Sep 26 22:05:44 2009 -0400
     4.2 +++ b/Japanese.lproj/MainMenu.xib	Mon Sep 28 21:51:03 2009 -0400
     4.3 @@ -1,19 +1,27 @@
     4.4  <?xml version="1.0" encoding="UTF-8"?>
     4.5 -<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.02">
     4.6 +<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="7.03">
     4.7  	<data>
     4.8  		<int key="IBDocument.SystemTarget">1050</int>
     4.9 -		<string key="IBDocument.SystemVersion">9E17</string>
    4.10 -		<string key="IBDocument.InterfaceBuilderVersion">670</string>
    4.11 -		<string key="IBDocument.AppKitVersion">949.33</string>
    4.12 -		<string key="IBDocument.HIToolboxVersion">352.00</string>
    4.13 +		<string key="IBDocument.SystemVersion">9L30</string>
    4.14 +		<string key="IBDocument.InterfaceBuilderVersion">677</string>
    4.15 +		<string key="IBDocument.AppKitVersion">949.54</string>
    4.16 +		<string key="IBDocument.HIToolboxVersion">353.00</string>
    4.17  		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
    4.18  			<bool key="EncodedWithXMLCoder">YES</bool>
    4.19 -			<integer value="1365"/>
    4.20  		</object>
    4.21  		<object class="NSArray" key="IBDocument.PluginDependencies">
    4.22  			<bool key="EncodedWithXMLCoder">YES</bool>
    4.23  			<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
    4.24  		</object>
    4.25 +		<object class="NSMutableDictionary" key="IBDocument.Metadata">
    4.26 +			<bool key="EncodedWithXMLCoder">YES</bool>
    4.27 +			<object class="NSArray" key="dict.sortedKeys">
    4.28 +				<bool key="EncodedWithXMLCoder">YES</bool>
    4.29 +			</object>
    4.30 +			<object class="NSMutableArray" key="dict.values">
    4.31 +				<bool key="EncodedWithXMLCoder">YES</bool>
    4.32 +			</object>
    4.33 +		</object>
    4.34  		<object class="NSMutableArray" key="IBDocument.RootObjects" id="271501155">
    4.35  			<bool key="EncodedWithXMLCoder">YES</bool>
    4.36  			<object class="NSCustomObject" id="90071088">
    4.37 @@ -740,13 +748,13 @@
    4.38  										<object class="NSTableView" id="937309307">
    4.39  											<reference key="NSNextResponder" ref="502387958"/>
    4.40  											<int key="NSvFlags">268</int>
    4.41 -											<string key="NSFrameSize">{368, 150}</string>
    4.42 +											<string key="NSFrameSize">{365, 150}</string>
    4.43  											<reference key="NSSuperview" ref="502387958"/>
    4.44  											<bool key="NSEnabled">YES</bool>
    4.45  											<object class="NSTableHeaderView" key="NSHeaderView" id="1034454722">
    4.46  												<reference key="NSNextResponder" ref="928819118"/>
    4.47  												<int key="NSvFlags">256</int>
    4.48 -												<string key="NSFrameSize">{368, 17}</string>
    4.49 +												<string key="NSFrameSize">{365, 17}</string>
    4.50  												<reference key="NSSuperview" ref="928819118"/>
    4.51  												<reference key="NSTableView" ref="937309307"/>
    4.52  											</object>
    4.53 @@ -918,7 +926,7 @@
    4.54  												</object>
    4.55  												<object class="NSTableColumn" id="935416875">
    4.56  													<string key="NSIdentifier">projectName</string>
    4.57 -													<double key="NSWidth">1.395610e+02</double>
    4.58 +													<double key="NSWidth">1.370000e+02</double>
    4.59  													<double key="NSMinWidth">6.000000e+01</double>
    4.60  													<double key="NSMaxWidth">5.000000e+02</double>
    4.61  													<object class="NSTableHeaderCell" key="NSHeaderCell">
    4.62 @@ -977,18 +985,18 @@
    4.63  									<reference key="NSSuperview" ref="170775034"/>
    4.64  									<reference key="NSTarget" ref="170775034"/>
    4.65  									<string key="NSAction">_doScroller:</string>
    4.66 -									<double key="NSPercent">7.894737e-01</double>
    4.67 +									<double key="NSCurValue">1.000000e+00</double>
    4.68 +									<double key="NSPercent">4.504505e-01</double>
    4.69  								</object>
    4.70  								<object class="NSScroller" id="1073263597">
    4.71  									<reference key="NSNextResponder" ref="170775034"/>
    4.72  									<int key="NSvFlags">256</int>
    4.73  									<string key="NSFrame">{{1, 167}, {365, 15}}</string>
    4.74  									<reference key="NSSuperview" ref="170775034"/>
    4.75 -									<bool key="NSEnabled">YES</bool>
    4.76  									<int key="NSsFlags">1</int>
    4.77  									<reference key="NSTarget" ref="170775034"/>
    4.78  									<string key="NSAction">_doScroller:</string>
    4.79 -									<double key="NSPercent">9.918478e-01</double>
    4.80 +									<double key="NSPercent">4.886211e-01</double>
    4.81  								</object>
    4.82  								<object class="NSClipView" id="928819118">
    4.83  									<reference key="NSNextResponder" ref="170775034"/>
    4.84 @@ -1009,11 +1017,12 @@
    4.85  							<string key="NSFrame">{{20, 20}, {382, 183}}</string>
    4.86  							<reference key="NSSuperview" ref="460762927"/>
    4.87  							<reference key="NSNextKeyView" ref="502387958"/>
    4.88 -							<int key="NSsFlags">178</int>
    4.89 +							<int key="NSsFlags">50</int>
    4.90  							<reference key="NSVScroller" ref="833943379"/>
    4.91  							<reference key="NSHScroller" ref="1073263597"/>
    4.92  							<reference key="NSContentView" ref="502387958"/>
    4.93  							<reference key="NSHeaderClipView" ref="928819118"/>
    4.94 +							<reference key="NSCornerView" ref="754285968"/>
    4.95  							<bytes key="NSScrollAmts">QSAAAEEgAABBmAAAQZgAAA</bytes>
    4.96  						</object>
    4.97  						<object class="NSBox" id="557104063">
    4.98 @@ -1163,7 +1172,7 @@
    4.99  									<object class="NSOutlineView" id="1021093117">
   4.100  										<reference key="NSNextResponder" ref="698826195"/>
   4.101  										<int key="NSvFlags">256</int>
   4.102 -										<string key="NSFrameSize">{251, 0}</string>
   4.103 +										<string key="NSFrameSize">{251, 178}</string>
   4.104  										<reference key="NSSuperview" ref="698826195"/>
   4.105  										<bool key="NSEnabled">YES</bool>
   4.106  										<object class="NSTableHeaderView" key="NSHeaderView" id="118124328">
   4.107 @@ -1298,6 +1307,7 @@
   4.108  						<reference key="NSHScroller" ref="1055430637"/>
   4.109  						<reference key="NSContentView" ref="698826195"/>
   4.110  						<reference key="NSHeaderClipView" ref="595734674"/>
   4.111 +						<reference key="NSCornerView" ref="1012082253"/>
   4.112  						<bytes key="NSScrollAmts">AAAAAAAAAABBmAAAQZgAAA</bytes>
   4.113  					</object>
   4.114  					<object class="NSButton" id="1034053726">
   4.115 @@ -1593,7 +1603,7 @@
   4.116  				<string key="NSTreeContentChildrenKey">subGroup</string>
   4.117  			</object>
   4.118  			<object class="NSCustomObject" id="799490416">
   4.119 -				<string key="NSClassName">DragController</string>
   4.120 +				<string key="NSClassName">TMProjectDragController</string>
   4.121  			</object>
   4.122  			<object class="NSArrayController" id="42796293">
   4.123  				<object class="NSMutableArray" key="NSDeclaredKeys">
   4.124 @@ -3572,18 +3582,42 @@
   4.125  					<string>1390.ImportedFromIB2</string>
   4.126  					<string>1391.IBPluginDependency</string>
   4.127  					<string>1391.ImportedFromIB2</string>
   4.128 +					<string>1393.IBPluginDependency</string>
   4.129 +					<string>1394.IBPluginDependency</string>
   4.130 +					<string>1395.IBPluginDependency</string>
   4.131 +					<string>1396.IBPluginDependency</string>
   4.132 +					<string>1397.IBPluginDependency</string>
   4.133 +					<string>1398.IBPluginDependency</string>
   4.134 +					<string>1399.IBPluginDependency</string>
   4.135 +					<string>1400.IBPluginDependency</string>
   4.136 +					<string>1401.IBPluginDependency</string>
   4.137 +					<string>1402.IBPluginDependency</string>
   4.138 +					<string>1403.IBPluginDependency</string>
   4.139 +					<string>1404.IBPluginDependency</string>
   4.140  					<string>1404.IBShouldRemoveOnLegacySave</string>
   4.141 +					<string>1405.IBPluginDependency</string>
   4.142  					<string>1405.IBShouldRemoveOnLegacySave</string>
   4.143 +					<string>1406.IBPluginDependency</string>
   4.144  					<string>1406.IBShouldRemoveOnLegacySave</string>
   4.145 +					<string>1407.IBPluginDependency</string>
   4.146  					<string>1407.IBShouldRemoveOnLegacySave</string>
   4.147 +					<string>1408.IBPluginDependency</string>
   4.148  					<string>1408.IBShouldRemoveOnLegacySave</string>
   4.149 +					<string>1409.IBPluginDependency</string>
   4.150  					<string>1409.IBShouldRemoveOnLegacySave</string>
   4.151 +					<string>1410.IBPluginDependency</string>
   4.152  					<string>1410.IBShouldRemoveOnLegacySave</string>
   4.153 +					<string>1411.IBPluginDependency</string>
   4.154  					<string>1411.IBShouldRemoveOnLegacySave</string>
   4.155 +					<string>1412.IBPluginDependency</string>
   4.156  					<string>1412.IBShouldRemoveOnLegacySave</string>
   4.157 +					<string>1413.IBPluginDependency</string>
   4.158  					<string>1413.IBShouldRemoveOnLegacySave</string>
   4.159 +					<string>1414.IBPluginDependency</string>
   4.160  					<string>1414.IBShouldRemoveOnLegacySave</string>
   4.161 +					<string>1415.IBPluginDependency</string>
   4.162  					<string>1415.IBShouldRemoveOnLegacySave</string>
   4.163 +					<string>1416.IBPluginDependency</string>
   4.164  					<string>1416.IBShouldRemoveOnLegacySave</string>
   4.165  					<string>144.IBPluginDependency</string>
   4.166  					<string>144.ImportedFromIB2</string>
   4.167 @@ -3600,7 +3634,6 @@
   4.168  					<string>29.IBEditorWindowLastContentRect</string>
   4.169  					<string>29.IBPluginDependency</string>
   4.170  					<string>29.ImportedFromIB2</string>
   4.171 -					<string>332.IBPluginDependency</string>
   4.172  					<string>332.ImportedFromIB2</string>
   4.173  					<string>332.windowTemplate.hasMinSize</string>
   4.174  					<string>332.windowTemplate.maxSize</string>
   4.175 @@ -3621,7 +3654,6 @@
   4.176  					<string>399.ImportedFromIB2</string>
   4.177  					<string>423.IBPluginDependency</string>
   4.178  					<string>423.ImportedFromIB2</string>
   4.179 -					<string>424.IBPluginDependency</string>
   4.180  					<string>424.ImportedFromIB2</string>
   4.181  					<string>424.NSWindowTemplate.visibleAtLaunch</string>
   4.182  					<string>424.windowTemplate.hasMinSize</string>
   4.183 @@ -3828,18 +3860,42 @@
   4.184  					<reference ref="5"/>
   4.185  					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.186  					<reference ref="5"/>
   4.187 -					<reference ref="5"/>
   4.188 -					<reference ref="5"/>
   4.189 -					<reference ref="5"/>
   4.190 -					<reference ref="5"/>
   4.191 -					<reference ref="5"/>
   4.192 -					<reference ref="5"/>
   4.193 -					<reference ref="5"/>
   4.194 -					<reference ref="5"/>
   4.195 -					<reference ref="5"/>
   4.196 -					<reference ref="5"/>
   4.197 -					<reference ref="5"/>
   4.198 -					<reference ref="5"/>
   4.199 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.200 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.201 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.202 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.203 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.204 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.205 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.206 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.207 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.208 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.209 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.210 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.211 +					<reference ref="5"/>
   4.212 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.213 +					<reference ref="5"/>
   4.214 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.215 +					<reference ref="5"/>
   4.216 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.217 +					<reference ref="5"/>
   4.218 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.219 +					<reference ref="5"/>
   4.220 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.221 +					<reference ref="5"/>
   4.222 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.223 +					<reference ref="5"/>
   4.224 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.225 +					<reference ref="5"/>
   4.226 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.227 +					<reference ref="5"/>
   4.228 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.229 +					<reference ref="5"/>
   4.230 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.231 +					<reference ref="5"/>
   4.232 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.233 +					<reference ref="5"/>
   4.234 +					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.235  					<reference ref="5"/>
   4.236  					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.237  					<reference ref="5"/>
   4.238 @@ -3856,7 +3912,6 @@
   4.239  					<string>{{78, 964}, {377, 20}}</string>
   4.240  					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.241  					<reference ref="5"/>
   4.242 -					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.243  					<reference ref="5"/>
   4.244  					<reference ref="5"/>
   4.245  					<string>{3.40282e+38, 3.40282e+38}</string>
   4.246 @@ -3877,7 +3932,6 @@
   4.247  					<reference ref="5"/>
   4.248  					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.249  					<reference ref="5"/>
   4.250 -					<string>com.apple.InterfaceBuilder.CocoaPlugin</string>
   4.251  					<reference ref="5"/>
   4.252  					<reference ref="5"/>
   4.253  					<reference ref="5"/>
   4.254 @@ -4032,28 +4086,8 @@
   4.255  			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
   4.256  				<bool key="EncodedWithXMLCoder">YES</bool>
   4.257  				<object class="IBPartialClassDescription">
   4.258 -					<string key="className">DragController</string>
   4.259 +					<string key="className">FirstResponder</string>
   4.260  					<string key="superclassName">NSObject</string>
   4.261 -					<object class="NSMutableDictionary" key="outlets">
   4.262 -						<bool key="EncodedWithXMLCoder">YES</bool>
   4.263 -						<object class="NSMutableArray" key="dict.sortedKeys">
   4.264 -							<bool key="EncodedWithXMLCoder">YES</bool>
   4.265 -							<string>groupTreeControl</string>
   4.266 -							<string>treeTable</string>
   4.267 -						</object>
   4.268 -						<object class="NSMutableArray" key="dict.values">
   4.269 -							<bool key="EncodedWithXMLCoder">YES</bool>
   4.270 -							<string>NSTreeController</string>
   4.271 -							<string>NSOutlineView</string>
   4.272 -						</object>
   4.273 -					</object>
   4.274 -					<object class="IBClassDescriptionSource" key="sourceIdentifier">
   4.275 -						<string key="majorKey">IBUserSource</string>
   4.276 -						<string key="minorKey"/>
   4.277 -					</object>
   4.278 -				</object>
   4.279 -				<object class="IBPartialClassDescription">
   4.280 -					<string key="className">FirstResponder</string>
   4.281  					<object class="IBClassDescriptionSource" key="sourceIdentifier">
   4.282  						<string key="majorKey">IBUserSource</string>
   4.283  						<string key="minorKey"/>
   4.284 @@ -4118,6 +4152,27 @@
   4.285  					</object>
   4.286  				</object>
   4.287  				<object class="IBPartialClassDescription">
   4.288 +					<string key="className">TMProjectDragController</string>
   4.289 +					<string key="superclassName">NSObject</string>
   4.290 +					<object class="NSMutableDictionary" key="outlets">
   4.291 +						<bool key="EncodedWithXMLCoder">YES</bool>
   4.292 +						<object class="NSMutableArray" key="dict.sortedKeys">
   4.293 +							<bool key="EncodedWithXMLCoder">YES</bool>
   4.294 +							<string>groupTreeControl</string>
   4.295 +							<string>treeTable</string>
   4.296 +						</object>
   4.297 +						<object class="NSMutableArray" key="dict.values">
   4.298 +							<bool key="EncodedWithXMLCoder">YES</bool>
   4.299 +							<string>NSTreeController</string>
   4.300 +							<string>NSOutlineView</string>
   4.301 +						</object>
   4.302 +					</object>
   4.303 +					<object class="IBClassDescriptionSource" key="sourceIdentifier">
   4.304 +						<string key="majorKey">IBUserSource</string>
   4.305 +						<string key="minorKey"/>
   4.306 +					</object>
   4.307 +				</object>
   4.308 +				<object class="IBPartialClassDescription">
   4.309  					<string key="className">TMTableView</string>
   4.310  					<string key="superclassName">NSTableView</string>
   4.311  					<object class="IBClassDescriptionSource" key="sourceIdentifier">
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/TMProjectDragController.h	Mon Sep 28 21:51:03 2009 -0400
     5.3 @@ -0,0 +1,25 @@
     5.4 +/* TimeMon
     5.5 +Copyright (C) 2009 Ceresalto
     5.6 +
     5.7 +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
     5.8 +as published by the Free Software Foundation; version 2 of the License.
     5.9 +
    5.10 +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    5.11 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
    5.12 +
    5.13 +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
    5.14 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
    5.15 +
    5.16 +@interface DragController : NSObject{
    5.17 +	IBOutlet NSTreeController *groupTreeControl;
    5.18 +	IBOutlet NSOutlineView *treeTable;
    5.19 +
    5.20 +	NSArray *dragType;
    5.21 +	NSTreeNode *draggedNode;
    5.22 +}
    5.23 +
    5.24 +- (BOOL)category:(NSManagedObject *)cat isSubCategoryOf:(NSManagedObject * )possibleSub;
    5.25 +- (void)resortGroups:(NSManagedObjectContext *)objectContext forParent:(NSManagedObject *)parent;
    5.26 +- (NSArray *)getSubGroups:(NSManagedObjectContext *)objectContext forParent:(NSManagedObject *)parent;
    5.27 +
    5.28 +@end
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/TMProjectDragController.m	Mon Sep 28 21:51:03 2009 -0400
     6.3 @@ -0,0 +1,268 @@
     6.4 +/* TimeMon
     6.5 +Copyright (C) 2009 Ceresalto
     6.6 +
     6.7 +This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License
     6.8 +as published by the Free Software Foundation; version 2 of the License.
     6.9 +
    6.10 +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of
    6.11 +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more details.
    6.12 +
    6.13 +You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software
    6.14 +Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.*/
    6.15 +
    6.16 +#import "DragController.h"
    6.17 +#import "NSTreeController_Extensions.h"
    6.18 +#import "CWCommonUtils.h"
    6.19 +
    6.20 +
    6.21 +@implementation DragController
    6.22 +- (void)awakeFromNib {
    6.23 +	dragType = [NSArray arrayWithObjects:@"factorialDragType", nil];
    6.24 +	[dragType retain];
    6.25 +	
    6.26 +	[groupTreeControl setSelectsInsertedObjects:YES];
    6.27 +	[treeTable registerForDraggedTypes:dragType];
    6.28 +	
    6.29 +	NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:@"position" ascending:YES];
    6.30 +	[groupTreeControl setSortDescriptors:[NSArray arrayWithObject: sortDesc]];
    6.31 +	[sortDesc release];
    6.32 +
    6.33 +	[[NSNotificationCenter defaultCenter] addObserver:self
    6.34 +											selector:@selector(startEditing:)
    6.35 +												name:@"TMNewProjectAdded"
    6.36 +											  object:nil];
    6.37 +	[[NSNotificationCenter defaultCenter] addObserver:self
    6.38 +											selector:@selector(sortObjects:)
    6.39 +												name:@"TMProjectsNeedResort"
    6.40 +											  object:nil];
    6.41 +	[[NSNotificationCenter defaultCenter] addObserver:self
    6.42 +											 selector:@selector(outlineViewItemDidExpand:)
    6.43 +												 name:@"NSOutlineViewItemDidExpandNotification"
    6.44 +											   object:nil];
    6.45 +	[[NSNotificationCenter defaultCenter] addObserver:self
    6.46 +											 selector:@selector(outlineViewItemDidCollapse:)
    6.47 +												 name:@"NSOutlineViewItemDidCollapseNotification"
    6.48 +											   object:nil];
    6.49 +}
    6.50 +
    6.51 +- (void)sortObjects:(NSNotification *)aNote{
    6.52 +	if (!IsEmpty(groupTreeControl.content)){
    6.53 +		[self resortGroups:[[groupTreeControl.content objectAtIndex:0] managedObjectContext] forParent:nil];
    6.54 +		[groupTreeControl rearrangeObjects];
    6.55 +	}
    6.56 +}
    6.57 +
    6.58 +- (void)startEditing:(NSNotification *)aNote{
    6.59 +	NSTreeNode *selectedNode;
    6.60 +	if (!IsEmpty(groupTreeControl.selectedNodes)){
    6.61 +		selectedNode = [groupTreeControl.selectedNodes objectAtIndex:0];
    6.62 +		
    6.63 +		//add some missing values
    6.64 +		[aNote.object setValue:[NSNumber numberWithInt:[[[selectedNode representedObject] valueForKey:@"position"] intValue]+1] forKey:@"position"];
    6.65 +		[aNote.object setValue:[[selectedNode representedObject] valueForKey:@"parent"] forKey:@"parent"];
    6.66 +	}
    6.67 +	else
    6.68 +		[aNote.object setValue:[NSNumber numberWithInt:-1] forKey:@"position"];
    6.69 +	
    6.70 +	//resort
    6.71 +	[self sortObjects:nil];
    6.72 +	
    6.73 +	//select the new object and start editing it
    6.74 +	NSTreeNode *node = [groupTreeControl treeNodeForObject:[[NSTreeNode treeNodeWithRepresentedObject:aNote.object] representedObject]];
    6.75 +	[groupTreeControl setSelectionIndexPath:node.indexPath];
    6.76 +	[treeTable editColumn:0 row:treeTable.selectedRow withEvent:nil select:YES];
    6.77 +	
    6.78 +	//undo registration; create a group for the insert and the name change
    6.79 +	[treeTable.undoManager beginUndoGrouping];
    6.80 +}
    6.81 +
    6.82 +//---------------------------------------------------------------------------
    6.83 +#pragma mark NSOutlineView datasource methods -- see NSOutlineViewDataSource
    6.84 +//---------------------------------------------------------------------------
    6.85 +- (BOOL)outlineView:(NSOutlineView *)outlineView writeItems:(NSArray *)items toPasteboard:(NSPasteboard *)pboard{
    6.86 +	[pboard declareTypes:dragType owner:self];
    6.87 +	// items is an array of NSTreeControllerTreeNodes
    6.88 +	draggedNode = [items objectAtIndex:0];
    6.89 +
    6.90 +	return YES;
    6.91 +}
    6.92 +
    6.93 +- (BOOL)outlineView:(NSOutlineView *)outlineView acceptDrop:(id <NSDraggingInfo>)info item:(id)item childIndex:(int)index{
    6.94 +	NSTreeNode *parentNode = item;
    6.95 +	NSTreeNode *siblingNode;
    6.96 +	NSTreeNode *proxy = groupTreeControl.arrangedObjects;
    6.97 +	NSManagedObject *draggedGroup = [draggedNode representedObject];
    6.98 +
    6.99 +	BOOL draggingDown = NO;
   6.100 +	BOOL isRootLevelDrag = NO;
   6.101 +
   6.102 +	// -------------------------
   6.103 +	// Setup comparison paths
   6.104 +	// -------------------------
   6.105 +	NSIndexPath *draggedPath = draggedNode.indexPath;
   6.106 +	NSIndexPath *siblingPath = [NSIndexPath indexPathWithIndex:index];
   6.107 +	if (!parentNode)
   6.108 +		isRootLevelDrag = YES;
   6.109 +	else
   6.110 +		// A non-root drag - the index value is relative to this parent's children
   6.111 +		siblingPath = [parentNode.indexPath indexPathByAddingIndex:index];
   6.112 +	
   6.113 +	// -----------------------------------------------------------------------------
   6.114 +	// Compare paths - modify sibling path for down drags, exit for redundant drags
   6.115 +	// -----------------------------------------------------------------------------
   6.116 +	switch ([draggedPath compare:siblingPath]){
   6.117 +		case NSOrderedAscending:  // reset path for down dragging
   6.118 +			if (isRootLevelDrag)
   6.119 +				siblingPath = [NSIndexPath indexPathWithIndex:index - 1];
   6.120 +			else
   6.121 +				siblingPath = [parentNode.indexPath indexPathByAddingIndex:index - 1];
   6.122 +			
   6.123 +			draggingDown = YES;
   6.124 +			break;
   6.125 +
   6.126 +		case NSOrderedSame:
   6.127 +			return NO;
   6.128 +			break;
   6.129 +	}
   6.130 +	
   6.131 +	siblingNode = [proxy descendantNodeAtIndexPath:siblingPath];
   6.132 +
   6.133 +	// ------------------------------------------------------------
   6.134 +	// SPECIAL CASE: Dragging to the bottom
   6.135 +	// ------------------------------------------------------------
   6.136 +	// - K                 - K              - C         - C
   6.137 +	// - - U               - - C     OR     - U         - F
   6.138 +	// - - C     ====>     - - F            - F         - K
   6.139 +	// - - F               - U              - K         - U
   6.140 +	// ------------------------------------------------------------
   6.141 +	if (isRootLevelDrag  && !siblingNode){
   6.142 +		draggingDown = YES;
   6.143 +		siblingPath = [NSIndexPath indexPathWithIndex:proxy.childNodes.count - 1];
   6.144 +		siblingNode = [proxy descendantNodeAtIndexPath:siblingPath];
   6.145 +	}
   6.146 +	
   6.147 +	// ------------------------------------------------------------
   6.148 +	// Give the dragged item a postion relative to it's new sibling
   6.149 +	// ------------------------------------------------------------
   6.150 +	NSManagedObject *sibling = [siblingNode representedObject];
   6.151 +	NSNumber *bystanderPosition = [sibling valueForKey:@"position"];
   6.152 +	int newPos = (draggingDown ? [bystanderPosition intValue] + 1 : [bystanderPosition intValue] - 1);
   6.153 +	[draggedGroup setValue:[NSNumber numberWithInt:newPos] forKey:@"position"];
   6.154 +	
   6.155 +	// ----------------------------------------------------------------------------------------------
   6.156 +	// Set the new parent for the dragged item, resort the position attributes and refresh the tree
   6.157 +	// ----------------------------------------------------------------------------------------------
   6.158 +	
   6.159 +	[draggedGroup setValue:[parentNode representedObject] forKey:@"parent"];
   6.160 +	
   6.161 +	[self resortGroups:[draggedGroup managedObjectContext] forParent:[parentNode representedObject]];
   6.162 +	[groupTreeControl rearrangeObjects];
   6.163 +	
   6.164 +	return YES;
   6.165 +}
   6.166 +
   6.167 +- (NSArray *)getSubGroups:(NSManagedObjectContext *)objectContext forParent:(NSManagedObject *)parent{
   6.168 +	NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
   6.169 +	NSEntityDescription *entity = [NSEntityDescription entityForName:@"projects" inManagedObjectContext:objectContext];
   6.170 +
   6.171 +	[request setEntity:entity];
   6.172 +	NSSortDescriptor *aSortDesc = [[NSSortDescriptor alloc] initWithKey:@"position" ascending:YES];
   6.173 +	[request setSortDescriptors:[NSArray arrayWithObject: aSortDesc]];
   6.174 +	[aSortDesc release];
   6.175 +
   6.176 +	NSPredicate *validationPredicate = [NSPredicate predicateWithFormat:@"parent == %@", parent];
   6.177 +
   6.178 +	[request setPredicate:validationPredicate];
   6.179 +
   6.180 +	NSError *error = nil;  // TODO - check the error bozo
   6.181 +	return [objectContext executeFetchRequest:request error:&error];
   6.182 +}
   6.183 +
   6.184 +- (void)resortGroups:(NSManagedObjectContext *)objectContext forParent:(NSManagedObject *)parent{
   6.185 +	NSArray *array = [self getSubGroups:objectContext forParent:parent];
   6.186 +
   6.187 +	// Reset the indexes...
   6.188 +	NSManagedObject *anObject;
   6.189 +	int index = 0;
   6.190 +	for (anObject in array){
   6.191 +		// Multiply index by 10 to make dragging code easier to implement ;) ....
   6.192 +		[anObject setValue:[NSNumber numberWithInt:(index * 10)] forKey:@"position"];
   6.193 +		index++;
   6.194 +	}
   6.195 +}
   6.196 +
   6.197 +- (NSDragOperation)outlineView:(NSOutlineView *)outlineView validateDrop:(id <NSDraggingInfo>)info proposedItem:(id)item proposedChildIndex:(int)index{
   6.198 +	NSTreeNode *newParent = item;
   6.199 +
   6.200 +	// drags to the root are always acceptable
   6.201 +	if (!newParent)
   6.202 +		return NSDragOperationGeneric;
   6.203 +
   6.204 +	// Verify that we are not dragging a parent to one of it's ancestors
   6.205 +	// causes a parent loop where a group of nodes point to each other and disappear
   6.206 +	// from the control
   6.207 +	NSManagedObject *dragged = [draggedNode representedObject];
   6.208 +	NSManagedObject *newP = [newParent representedObject];
   6.209 +
   6.210 +	if ([self category:dragged isSubCategoryOf:newP])
   6.211 +		return NO;
   6.212 +	
   6.213 +	return NSDragOperationGeneric;
   6.214 +}
   6.215 +
   6.216 +- (BOOL)category:(NSManagedObject *)cat isSubCategoryOf:(NSManagedObject *)possibleSub{
   6.217 +	// Depends on your interpretation of subCategory ....
   6.218 +	if (cat == possibleSub)
   6.219 +		return YES;
   6.220 +
   6.221 +	NSManagedObject *possSubParent = [possibleSub valueForKey:@"parent"];
   6.222 +
   6.223 +	if (!possSubParent)
   6.224 +		return NO;
   6.225 +
   6.226 +	while (possSubParent){
   6.227 +		if (possSubParent == cat)
   6.228 +			return YES;
   6.229 +		// move up the tree
   6.230 +		possSubParent = [possSubParent valueForKey:@"parent"];
   6.231 +	}
   6.232 +	
   6.233 +	return NO;
   6.234 +}
   6.235 +
   6.236 +- (BOOL)canRemove
   6.237 +{
   6.238 +	return treeTable.selectedRow >= 0;
   6.239 +}
   6.240 +
   6.241 +/*
   6.242 +The following are implemented as stubs because they are required when
   6.243 + implementing an NSOutlineViewDataSource. Because we use bindings on the
   6.244 + table column these methods are never called. The NSLog statements have been
   6.245 + included to prove that these methods are not called.
   6.246 + */
   6.247 +- (int)outlineView:(NSOutlineView *)ov numberOfChildrenOfItem:(id)item{
   6.248 +	return 0;
   6.249 +}
   6.250 +
   6.251 +- (BOOL)outlineView:(NSOutlineView *)ov isItemExpandable:(id)item{
   6.252 +	return NO;
   6.253 +}
   6.254 +
   6.255 +- (id)outlineView:(NSOutlineView *)ov child:(int)index ofItem:(id)item{
   6.256 +	return nil;
   6.257 +}
   6.258 +
   6.259 +- (id)outlineView:(NSOutlineView *)ov objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item{
   6.260 +	return nil;
   6.261 +}
   6.262 +
   6.263 +- (void)outlineViewItemDidExpand:(NSNotification *)notification{
   6.264 +	[[[notification.userInfo valueForKey:@"NSObject"] representedObject] setValue:[NSNumber numberWithBool:YES] forKey:@"expandedState"];
   6.265 +}
   6.266 +
   6.267 +- (void)outlineViewItemDidCollapse:(NSNotification *)notification{
   6.268 +	[[[notification.userInfo valueForKey:@"NSObject"] representedObject] setValue:[NSNumber numberWithBool:NO] forKey:@"expandedState"];
   6.269 +}
   6.270 +
   6.271 +@end
     7.1 --- a/TimeMon.xcodeproj/project.pbxproj	Sat Sep 26 22:05:44 2009 -0400
     7.2 +++ b/TimeMon.xcodeproj/project.pbxproj	Mon Sep 28 21:51:03 2009 -0400
     7.3 @@ -14,8 +14,8 @@
     7.4  		012E50420A37A24F000F4614 /* TMDefaultsController.m in Sources */ = {isa = PBXBuildFile; fileRef = 012E50400A37A24F000F4614 /* TMDefaultsController.m */; };
     7.5  		012E50430A37A24F000F4614 /* TMDefaultsController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 012E50410A37A24F000F4614 /* TMDefaultsController.h */; };
     7.6  		015CA0480A100340007A9CC5 /* tm_clocked_in.icns in Resources */ = {isa = PBXBuildFile; fileRef = 015CA0470A100340007A9CC5 /* tm_clocked_in.icns */; };
     7.7 -		0181E0900A375E02002B95CC /* DragController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0181E08E0A375E02002B95CC /* DragController.h */; };
     7.8 -		0181E0910A375E02002B95CC /* DragController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0181E08F0A375E02002B95CC /* DragController.m */; };
     7.9 +		0181E0900A375E02002B95CC /* TMProjectDragController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 0181E08E0A375E02002B95CC /* TMProjectDragController.h */; };
    7.10 +		0181E0910A375E02002B95CC /* TMProjectDragController.m in Sources */ = {isa = PBXBuildFile; fileRef = 0181E08F0A375E02002B95CC /* TMProjectDragController.m */; };
    7.11  		01A919FF0A8FF5B5006C9F1D /* TMArrayController.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 01A919FD0A8FF5B5006C9F1D /* TMArrayController.h */; };
    7.12  		01A91A000A8FF5B5006C9F1D /* TMArrayController.m in Sources */ = {isa = PBXBuildFile; fileRef = 01A919FE0A8FF5B5006C9F1D /* TMArrayController.m */; };
    7.13  		01E27E000A8AACB900282BF1 /* tm_on_break.icns in Resources */ = {isa = PBXBuildFile; fileRef = 01E27DFF0A8AACB900282BF1 /* tm_on_break.icns */; };
    7.14 @@ -102,7 +102,7 @@
    7.15  			dstPath = "";
    7.16  			dstSubfolderSpec = 6;
    7.17  			files = (
    7.18 -				0181E0900A375E02002B95CC /* DragController.h in CopyFiles */,
    7.19 +				0181E0900A375E02002B95CC /* TMProjectDragController.h in CopyFiles */,
    7.20  				012E50430A37A24F000F4614 /* TMDefaultsController.h in CopyFiles */,
    7.21  				01121A570A6473730008E2B6 /* TMDuration.h in CopyFiles */,
    7.22  				01A919FF0A8FF5B5006C9F1D /* TMArrayController.h in CopyFiles */,
    7.23 @@ -120,8 +120,8 @@
    7.24  		012E50400A37A24F000F4614 /* TMDefaultsController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = TMDefaultsController.m; sourceTree = "<group>"; };
    7.25  		012E50410A37A24F000F4614 /* TMDefaultsController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TMDefaultsController.h; sourceTree = "<group>"; };
    7.26  		015CA0470A100340007A9CC5 /* tm_clocked_in.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = tm_clocked_in.icns; path = images/tm_clocked_in.icns; sourceTree = "<group>"; };
    7.27 -		0181E08E0A375E02002B95CC /* DragController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = DragController.h; sourceTree = "<group>"; };
    7.28 -		0181E08F0A375E02002B95CC /* DragController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = DragController.m; sourceTree = "<group>"; };
    7.29 +		0181E08E0A375E02002B95CC /* TMProjectDragController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TMProjectDragController.h; sourceTree = "<group>"; };
    7.30 +		0181E08F0A375E02002B95CC /* TMProjectDragController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = TMProjectDragController.m; sourceTree = "<group>"; };
    7.31  		01A919FD0A8FF5B5006C9F1D /* TMArrayController.h */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.h; path = TMArrayController.h; sourceTree = "<group>"; };
    7.32  		01A919FE0A8FF5B5006C9F1D /* TMArrayController.m */ = {isa = PBXFileReference; fileEncoding = 30; lastKnownFileType = sourcecode.c.objc; path = TMArrayController.m; sourceTree = "<group>"; };
    7.33  		01E27DFF0A8AACB900282BF1 /* tm_on_break.icns */ = {isa = PBXFileReference; lastKnownFileType = image.icns; name = tm_on_break.icns; path = images/tm_on_break.icns; sourceTree = "<group>"; };
    7.34 @@ -395,8 +395,8 @@
    7.35  				5A71DE510D08FB3C003F6DF9 /* TMOutline.m */,
    7.36  				5A71DE520D08FB3C003F6DF9 /* TMTableView.h */,
    7.37  				5A71DE530D08FB3C003F6DF9 /* TMTableView.m */,
    7.38 -				0181E08E0A375E02002B95CC /* DragController.h */,
    7.39 -				0181E08F0A375E02002B95CC /* DragController.m */,
    7.40 +				0181E08E0A375E02002B95CC /* TMProjectDragController.h */,
    7.41 +				0181E08F0A375E02002B95CC /* TMProjectDragController.m */,
    7.42  				5AF60F760DD68514005B58DA /* ImageAndTextCell.h */,
    7.43  				5AF60F770DD68514005B58DA /* ImageAndTextCell.m */,
    7.44  			);
    7.45 @@ -481,7 +481,7 @@
    7.46  				CEB665FD09A645E40045622B /* TMPreferences.m in Sources */,
    7.47  				CEB6664D09A660E10045622B /* TMNotesPanel.m in Sources */,
    7.48  				CEDDD37D09A788C6005669F8 /* TMHistoryView.m in Sources */,
    7.49 -				0181E0910A375E02002B95CC /* DragController.m in Sources */,
    7.50 +				0181E0910A375E02002B95CC /* TMProjectDragController.m in Sources */,
    7.51  				012E50420A37A24F000F4614 /* TMDefaultsController.m in Sources */,
    7.52  				01121A580A6473730008E2B6 /* TMDuration.m in Sources */,
    7.53  				01A91A000A8FF5B5006C9F1D /* TMArrayController.m in Sources */,