Created
November 17, 2011 00:16
-
-
Save chadmoone/1371970 to your computer and use it in GitHub Desktop.
Undo-Redo Idea
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
- (IBAction)createFrame:(id)sender | |
{ | |
NSString *frameType = [frameTypeComboBox stringValue]; | |
id newFrame = (NSManagedObject *)[NSClassFromString(frameType) createEntity]; | |
[newFrame setValue:frameType forKey:@"frameType"]; | |
[newFrame setValue:[[sectionObjectController content] valueForKey:@"identifier"] forKey:@"sectionID"]; | |
[self addObjectToFramesArrayController:newFrame]; | |
} | |
- (IBAction)deleteFrame:(id)sender | |
{ | |
id selectedFrame = [[framesArrayController selectedObjects] lastObject]; | |
[self removeObjectFromFramesArrayController:selectedFrame]; | |
} | |
- (void)addObjectToFramesArrayController:(Frame *)f | |
{ | |
void (^successBlock)(NSManagedObject *object) = ^(NSManagedObject *object) { | |
// If the remoting fails, the object is deleted, so only add to undo on success | |
// Register Undo | |
NSUndoManager *undo = [self undoManager]; | |
[[undo prepareWithInvocationTarget:self] removeObjectFromFramesArrayController:f]; | |
// Only set the action name if we're not undoing. | |
// This way, when this method is called during 'Undo Delete Frame', the action item will end up in redo as 'Redo Delete Frame' | |
if (![undo isUndoing]) { | |
[undo setActionName:@"Add Frame"]; | |
} | |
}; | |
NSDictionary *action = [NSDictionary dictionaryWithObjectsAndKeys:f, RemoteObject, successBlock, SuccessBlock, nil]; | |
[NSApp sendAction:@selector(postObject:) to:nil from:action]; | |
} | |
- (void)removeObjectFromFramesArrayController:(Frame *)f | |
{ | |
void (^successBlock)(NSManagedObject *object) = ^(NSManagedObject *object) { | |
// If the remoting fails, the object is not deleted, so only add to undo on success | |
// Get JSON for string (could also be a clone) | |
NSString *json = [f json]; | |
NSUndoManager *undo = [self undoManager]; | |
[[undo prepareWithInvocationTarget:self] createFrameFromJSON:json]; | |
// Only set the action name if we're not undoing. | |
// This way, when this method is called during 'Undo Add Frame', the action item will end up in redo as 'Redo Add Frame' | |
if (![undo isUndoing]) { | |
[undo setActionName:@"Delete Frame"]; | |
} | |
}; | |
NSDictionary *action = [NSDictionary dictionaryWithObjectsAndKeys:f, RemoteObject, successBlock, SuccessBlock, nil]; | |
[NSApp sendAction:@selector(postObject:) to:nil from:action]; | |
} | |
- (void)createFrameFromJSON:(NSString *)s | |
{ | |
// create frame from JSON | |
[self addObjectToFramesArrayController:newFrame]; | |
} | |
// Also, we could potentially use KVO to handle edits, although I don't know how this works with nested objects | |
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context | |
{ | |
NSUndoManager *undo = [self undoManager]; | |
id oldValue = [change objectForKey:NSKeyValueChangeOldKey]; | |
// NSNull objects are used to represent nil in a dictionary | |
if (oldValue == [NSNull null]) { | |
oldValue = nil; | |
} | |
[[undo prepareWithInvocationTarget:self] changeKeyPath:keyPath ofObject:object toValue:oldValue]; | |
[undo setActionName:@"Edit Frame"]; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment