Skip to content

Commit

Permalink
True undo/redo support
Browse files Browse the repository at this point in the history
closes #13
  • Loading branch information
daylen committed Dec 30, 2014
1 parent b381ca0 commit 4825262
Show file tree
Hide file tree
Showing 5 changed files with 61 additions and 13 deletions.
13 changes: 9 additions & 4 deletions Stockfish/Base.lproj/MainMenu.xib
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="5056" systemVersion="14A329r" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="6254" systemVersion="14C81f" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment defaultVersion="1080" identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="5056"/>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="6254"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="SFMApplication"/>
Expand Down Expand Up @@ -117,7 +117,12 @@
<items>
<menuItem title="Undo" keyEquivalent="z" id="5ci-kw-TuF">
<connections>
<action selector="undoLastMove:" target="-1" id="sGd-qq-xhV"/>
<action selector="undo:" target="-1" id="Qqx-dG-bUW"/>
</connections>
</menuItem>
<menuItem title="Redo" keyEquivalent="Z" id="AG5-uF-MgE">
<connections>
<action selector="redo:" target="-1" id="sxc-px-OiJ"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="ocq-4a-j2L"/>
Expand Down
13 changes: 12 additions & 1 deletion Stockfish/SFMChessGame.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,27 @@
#import "SFMPosition.h"
#import "SFMMove.h"

@class SFMChessGame;

@protocol SFMChessGameDelegate <NSObject>

- (void)chessGameStateDidChange:(SFMChessGame *)chessGame;

@end

/*!
SFMChessGame contains PGN metadata and move history for a game.
*/
@interface SFMChessGame : NSObject <NSCopying>

#pragma mark - Properties

@property (nonatomic) id<SFMChessGameDelegate> delegate;

@property (nonatomic) NSDictionary *tags;
@property (nonatomic, readonly) SFMPosition *position;
@property (readonly) NSUInteger currentMoveIndex;
@property (nonatomic) NSUndoManager *undoManager;

#pragma mark - Init

Expand Down Expand Up @@ -64,7 +75,7 @@
@param index
@return An array of deleted moves.
*/
- (NSArray *)deleteMovesFromPly:(NSInteger)index;
- (NSArray *)deleteMovesFromPly:(NSNumber *)index;

/*!
Set the result of the game.
Expand Down
23 changes: 22 additions & 1 deletion Stockfish/SFMChessGame.m
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ - (instancetype)init {
_moves = [[NSMutableArray alloc] init];
_currentMoveIndex = 0;
_position = [[SFMPosition alloc] init];
_undoManager = [[NSUndoManager alloc] init];
}
return self;
}
Expand All @@ -58,6 +59,7 @@ - (instancetype)initWithTags:(NSDictionary *)tags moveText:(NSString *)moveText
_moveText = moveText;
_currentMoveIndex = 0;
_position = [[SFMPosition alloc] initWithFen:_tags[@"FEN"] ? _tags[@"FEN"] : FEN_START_POSITION];
_undoManager = [[NSUndoManager alloc] init];
}
return self;
}
Expand All @@ -83,6 +85,9 @@ - (void)parseMoveText:(NSError *__autoreleasing *)error {
#pragma mark - State Modification

- (BOOL)doMove:(SFMMove *)move error:(NSError *__autoreleasing *)error {
NSAssert(move, @"Move is nil");

[self.undoManager registerUndoWithTarget:self selector:@selector(deleteMovesFromPly:) object:@(self.currentMoveIndex)];

if (![self atEnd]) {
*error = [NSError errorWithDomain:GAME_ERROR_DOMAIN code:NOT_AT_END_CODE userInfo:nil];
Expand All @@ -98,10 +103,16 @@ - (BOOL)doMove:(SFMMove *)move error:(NSError *__autoreleasing *)error {

self.currentMoveIndex++;
[self.moves addObject:move];

[self.delegate chessGameStateDidChange:self];
return YES;
}

- (BOOL)doMoves:(NSArray *)moves error:(NSError *__autoreleasing *)error {
NSAssert(moves && [moves count] > 0, @"Moves array is nil or has nothing");

[self.undoManager registerUndoWithTarget:self selector:@selector(deleteMovesFromPly:) object:@(self.currentMoveIndex)];

NSError *e = nil;
for (SFMMove *move in moves) {
[self doMove:move error:&e];
Expand All @@ -110,13 +121,23 @@ - (BOOL)doMoves:(NSArray *)moves error:(NSError *__autoreleasing *)error {
return NO;
}
}

[self.delegate chessGameStateDidChange:self];
return YES;
}

- (NSArray *)deleteMovesFromPly:(NSInteger)index {
- (NSArray *)deleteMovesFromPly:(NSNumber *)idx {
NSUInteger index = [idx integerValue];
NSArray *toDelete = [self.moves subarrayWithRange:NSMakeRange(index, [self.moves count] - index)];
if (!toDelete || [toDelete count] == 0) {
return nil;
}

[[self.undoManager prepareWithInvocationTarget:self] doMoves:toDelete error:nil];
[self.moves removeObjectsInRange:NSMakeRange(index, [self.moves count] - index)];
[self goToEnd];

[self.delegate chessGameStateDidChange:self];
return toDelete;
}

Expand Down
3 changes: 2 additions & 1 deletion Stockfish/SFMWindowController.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
#import "SFMPGNFile.h"
#import "SFMBoardView.h"
#import "SFMUCIEngine.h"
#import "SFMChessGame.h"

@interface SFMWindowController : NSWindowController <NSTableViewDataSource, NSTableViewDelegate, NSWindowDelegate, SFMBoardViewDataSource, SFMBoardViewDelegate, SFMUCIEngineDelegate>
@interface SFMWindowController : NSWindowController <NSTableViewDataSource, NSTableViewDelegate, NSWindowDelegate, SFMBoardViewDataSource, SFMBoardViewDelegate, SFMUCIEngineDelegate, SFMChessGameDelegate>

@property SFMPGNFile *pgnFile;

Expand Down
22 changes: 16 additions & 6 deletions Stockfish/SFMWindowController.m
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ @interface SFMWindowController ()
@implementation SFMWindowController

#pragma mark - Target/Action

- (IBAction)copyFenString:(id)sender
{
NSMutableString *fen = [self.currentGame.position.fen mutableCopy];
Expand Down Expand Up @@ -91,9 +92,6 @@ - (IBAction)lastMove:(id)sender {
[self.currentGame goToEnd];
[self syncToViewsAndEngine];
}
- (IBAction)undoLastMove:(id)sender {
// TODO real undo support
}
- (IBAction)toggleInfiniteAnalysis:(id)sender {
if (self.engine.isAnalyzing) {
self.engine.isAnalyzing = NO;
Expand Down Expand Up @@ -184,11 +182,12 @@ - (void)loadGameAtIndex:(int)index
{
self.currentGameIndex = index;
self.currentGame = self.pgnFile.games[index];
self.currentGame.delegate = self;
NSError *error = nil;
[self.currentGame parseMoveText:&error];
if (error) {
[self close];
NSAlert *alert = [NSAlert alertWithMessageText:@"Could not open game" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"%@", [error description]];
NSAlert *alert = [NSAlert alertWithMessageText:@"Could not open game" defaultButton:@"OK" alternateButton:nil otherButton:nil informativeTextWithFormat:@"Stockfish could not parse the move text. Edit your PGN file and try again."];
[alert runModal];
}

Expand Down Expand Up @@ -295,11 +294,22 @@ - (SFMMove *)firstMoveFromPV:(NSString *)pv
return [[self.currentGame.position movesArrayForUci:[pv componentsSeparatedByString:@" "]] firstObject];
}

#pragma mark - SFMChessGameDelegate

- (void)chessGameStateDidChange:(SFMChessGame *)chessGame {
[self syncToViewsAndEngine];
}

#pragma mark - NSWindowDelegate

- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window {
return self.currentGame.undoManager;
}

#pragma mark - SFMBoardViewDelegate

- (void)boardView:(SFMBoardView *)boardView userDidMove:(SFMMove *)move {
[self doMoveWithOverwritePrompt:move];

}

- (void)doMoveWithOverwritePrompt:(SFMMove *)move {
Expand All @@ -309,7 +319,7 @@ - (void)doMoveWithOverwritePrompt:(SFMMove *)move {
switch (returnCode) {
case 1:
// Overwrite
[self.currentGame deleteMovesFromPly:self.currentGame.currentMoveIndex];
[self.currentGame deleteMovesFromPly:@(self.currentGame.currentMoveIndex)];
[self doMoveForced:move];
break;
case 0:
Expand Down

0 comments on commit 4825262

Please sign in to comment.