NSUndoManager(Chapter 9 of Cocoa Programming for Mac OS X)_#importNSUndoManager(Chapter 9 of Cocoa Programming for Mac OS X)_学习_02Document
  1 //
  2 //  MyDocument.m
  3 //  RaiseMan
  4 //
  5 //  Created by b1mobile on 2/14/11.
  6 //  Copyright 2011 __MyCompanyName__. All rights reserved.
  7 //
  8 
  9 #import "MyDocument.h"
 10 #import "Person.h"
 11 
 12 @implementation MyDocument
 13 
 14 - (id)init
 15 {
 16     self = [super init];
 17     employees = [[NSMutableArray alloc] init];
 18     return self;
 19 }
 20 
 21 - (void)dealloc
 22 {
 23     [super setEmployees:nil];
 24     [super dealloc];
 25 }
 26 
 27 - (void)setEmployees:(NSMutableArray *)a
 28 {
 29     if(a == employees)
 30     {
 31         return;
 32     }
 33     
 34     for(Person *person in employees)
 35     {
 36         [self stopObservingPerson:person];
 37     }
 38     
 39     [a retain];
 40     [employees release];
 41     employees = a;
 42     
 43     for(Person *person in employees)
 44     {
 45         [self startObservingPerson:person];
 46     }
 47 }
 48 
 49 - (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index
 50 {
 51     NSLog(@"adding %@ to %@", p, employees);
 52     NSUndoManager *undo = [self undoManager];
 53     [[undo prepareWithInvocationTarget:self] removeObjectFromEmployeesAtIndex:index];
 54     if(![undo isUndoing])
 55     {
 56         [undo setActionName:@"Insert Person"];
 57     }
 58     [self startObservingPerson:p];
 59     [employees insertObject:p atIndex:index];
 60 }
 61 
 62 - (void)removeObjectFromEmployeesAtIndex:(int)index
 63 {
 64     Person *= [employees objectAtIndex:index];
 65     NSLog(@"removing %@ from %@", p, employees);
 66     NSUndoManager *undo = [self undoManager];
 67     [[undo prepareWithInvocationTarget:self] insertObject:p inEmployeesAtIndex:index];
 68     
 69     if(![undo isUndoing])
 70     {
 71         [undo setActionName:@"Delete Person"];
 72     }
 73     [self stopObservingPerson:p];
 74     [employees removeObjectAtIndex:index];
 75 }
 76 
 77 - (void)startObservingPerson:(Person *)person
 78 {
 79     [person addObserver:self forKeyPath:@"personName" options:NSKeyValueObservingOptionOld context:NULL];
 80     [person    addObserver:self forKeyPath:@"expectedRaise" options:NSKeyValueObservingOptionOld context:NULL];
 81 }
 82 
 83 - (void)stopObservingPerson:(Person *)person
 84 {
 85     [person removeObserver:self forKeyPath:@"personName"];
 86     [person    removeObserver:self forKeyPath:@"expectedRaise"];
 87 }
 88 
 89 - (void)changeKeyPath:(NSString *)keyPath ofObject:(id)obj toValue:(id)newValue
 90 {
 91     [obj setValue:newValue forKeyPath:keyPath];
 92 }
 93 
 94 - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
 95 {
 96     NSUndoManager *undo = [self undoManager];
 97     id oldValue = [change objectForKey:NSKeyValueChangeOldKey];
 98     
 99     if(oldValue == [NSNull null])
100     {
101         oldValue = nil;
102     }
103     
104     NSLog(@"oldValue = %@", oldValue);
105     [[undo prepareWithInvocationTarget:self] changeKeyPath:keyPath ofObject:object toValue:oldValue];
106     [undo setActionName:@"Edit"];
107 }
108 
109 - (IBAction)createEmployee:(id)sender
110 {
111     NSWindow *= [tableView window];
112     
113     BOOL editingEnded = [w makeFirstResponder:w];
114     if(!editingEnded)
115     {
116         NSLog(@"Unable to end editing");
117         return;
118     }
119     
120     NSUndoManager *undo = [self undoManager];
121     if ([undo groupingLevel]) 
122     {
123         [undo endUndoGrouping];
124         [undo beginUndoGrouping];
125     }
126     Person *= [employeeController newObject];
127     [employeeController addObject:p];
128     [p release];
129     [employeeController rearrangeObjects];
130     
131     NSArray *= [employeeController arrangedObjects];
132     int row = [a indexOfObjectIdenticalTo:p];
133     NSLog(@"starting edit of %@ in row %@", p, row);
134     [tableView editColumn:0 row:row withEvent:nil select:YES];
135 }
136 
137 - (NSString *)windowNibName
138 {
139     // Override returning the nib file name of the document
140     // If you need to use a subclass of NSWindowController or if your document supports multiple NSWindowControllers, you should remove this method and override -makeWindowControllers instead.
141     return @"MyDocument";
142 }
143 
144 - (void)windowControllerDidLoadNib:(NSWindowController *) aController
145 {
146     [super windowControllerDidLoadNib:aController];
147     // Add any code here that needs to be executed once the windowController has loaded the document's window.
148 }
149 
150 - (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError
151 {
152     // Insert code here to write your document to data of the specified type. If the given outError != NULL, ensure that you set *outError when returning nil.
153 
154     // You can also choose to override -fileWrapperOfType:error:, -writeToURL:ofType:error:, or -writeToURL:ofType:forSaveOperation:originalContentsURL:error: instead.
155 
156     // For applications targeted for Panther or earlier systems, you should use the deprecated API -dataRepresentationOfType:. In this case you can also choose to override -fileWrapperRepresentationOfType: or -writeToFile:ofType: instead.
157 
158     if ( outError != NULL ) {
159         *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
160     }
161     return nil;
162 }
163 
164 - (BOOL)readFromData:(NSData *)data ofType:(NSString *)typeName error:(NSError **)outError
165 {
166     // Insert code here to read your document from the given data of the specified type.  If the given outError != NULL, ensure that you set *outError when returning NO.
167 
168     // You can also choose to override -readFromFileWrapper:ofType:error: or -readFromURL:ofType:error: instead. 
169     
170     // For applications targeted for Panther or earlier systems, you should use the deprecated API -loadDataRepresentation:ofType. In this case you can also choose to override -readFromFile:ofType: or -loadFileWrapperRepresentation:ofType: instead.
171     
172     if ( outError != NULL ) {
173         *outError = [NSError errorWithDomain:NSOSStatusErrorDomain code:unimpErr userInfo:NULL];
174     }
175     return YES;
176 }
177 
178 @end
179