Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

stadidas

macrumors regular
Original poster
Feb 27, 2006
243
0
Kent, United Kingdom
Hi everyone,

I'm having a bit of an issue with the undo manager and bindings which I'm sure someone here can help me out with.
In my MyDocument class I have a reference to an instance of DocumentModel, which has the following attributes:

Code:
@interface DocumentModel : NSObject
{
	double currentBalance;
	double amountToSave;
	double moneyToSpendPerDay;
	double moneyToSpendPerWeek;
	
	int weeksLeft;
	int daysLeft;
	int numberOfDays;
	
	NSCalendarDate *endOfTermDate;
	
	int saveCheckbox;
	
	NSMutableArray *logEntries;
}


This instance of DocumentModel has an instance of NSObjectController bound to it. I then have an NSArrayController that I bind to the 'logEntries' key of the ObjectController, in order to control the logEntries MutableArray.
This is all working perfectly well. However, I wish to override the insert and remove methods of the NSArrayController, and in the process make use of undo / redo :

Code:
- (void)insertObject:(LogEntry *)newLog inLogEntriesAtIndex:(int)index
{
	NSUndoManager *undo = [self undoManager];
	[[undo prepareWithInvocationTarget:self]
		removeObjectFromLogEntriesAtIndex:index];
	
	NSString *undoText;
	if(newLog.typeFlag == BALANCE_CHANGE_FLAG)
	{
		undoText = [NSString stringWithFormat:@"Balance Change"];
	}
	else
	{
		undoText = [NSString stringWithFormat:@"Add '%@'", newLog.transactionDescription];
	}
	
	if(![undo isUndoing])
	{
		[undo setActionName:undoText ];
	}
	
	[logEntries insertObject:newLog atIndex:index];
	[self calculateBalanceAndBudget];
}

- (void)removeObjectFromLogEntriesAtIndex:(int)index
{
	
	LogEntry *entry = [logEntries objectAtIndex:index];
	NSUndoManager *undo = [self undoManager];
	[[undo prepareWithInvocationTarget:self]
		 insertObject:entry inLogEntriesAtIndex:index];
	
	NSString *undoText;
	if(entry.typeFlag == BALANCE_CHANGE_FLAG)
	{
		undoText = [NSString stringWithFormat:@"Delete Balance Change"];
	}
	else
	{
		undoText = [NSString stringWithFormat:@"Delete '%@'", entry.transactionDescription];
	}
	
	if(![undo isUndoing])
	{
		[undo setActionName:undoText ];
	}
	
	[logEntries removeObjectAtIndex:index];
	[self calculateBalanceAndBudget];
}

I have tried putting these methods in MyDocument and in the DocumentModel objects, but whenever I add an entry nothing is put in the undo manager.
If anyone can shed any light on the issue I would much appreciate it!
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
Are you sure the NSUndoManager has been properly setup? What does [self hasUndoManager]; return?
 

stadidas

macrumors regular
Original poster
Feb 27, 2006
243
0
Kent, United Kingdom
Are you sure the NSUndoManager has been properly setup? What does [self hasUndoManager]; return?

Hi Kainjow,

I put the following print statement in the insertObject method of DataModel:

Code:
NSLog(@"DataModel UndoManager: %@", [self hasUndoManager]);

which printed "*** -[DocumentModel hasUndoManager]: unrecognized selector sent to instance 0x1042c60" to the console. I take it from this that I have not got NSUndoManager correctly set up for this class. How would I go about doing this?
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
Oops I thought your DocumentModel object was a NSDocument subclass. What about your [self undoManager] code. Can you post that?
 

stadidas

macrumors regular
Original poster
Feb 27, 2006
243
0
Kent, United Kingdom
Oops I thought your DocumentModel object was a NSDocument subclass. What about your [self undoManager] code. Can you post that?

Ah no, MyDocument keeps a reference to an instance of DocumentModel. Calling [self undoManager] on DocumentModel returns:
*** -[DocumentModel undoManager]: unrecognized selector sent to instance 0x1044fa0

Is it an acceptable form of obtaining a reference to the document undoManager to just pass a reference to the DocumentModel object at creation from MyDocument. For example to have a variable named 'undoManager' in DocumentModel and then call
Code:
[documentModel setUndoManager:[self undoManager]];

from MyDocument?
 

kainjow

Moderator emeritus
Jun 15, 2000
7,958
7
Ok I'm confused then.

In your original post, where are those methods being used? MyDocument or DocumentModel? If MyDocument, then the undoManager methods are fine since NSDocument maintains its own NSUndoManager, but you probably need to make sure setHasUndoManager: returns YES first. If you're calling them in DocumentModel, it will not work unless you have an undoManager method defined.
 

stadidas

macrumors regular
Original poster
Feb 27, 2006
243
0
Kent, United Kingdom
If you're calling them in DocumentModel, it will not work unless you have an undoManager method defined.

They are being called in DocumentModel. I have now added NSUndoManager *undoManager to DocumentModel, and pass it an undoManager from MyDocument like this:

Code:
documentModel.undoManager = [self undoManager];

I have edited the insert and remove methods to use this undoManager reference and it all works now, Cheers for your help, you've been very handy as always.
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.