DBUndoManager - Historique d'annulation

fouffouf Membre
décembre 2007 modifié dans Objective-C, Swift, C, C++ #1
Voila donc du code pour faire un véritable historique d'annulation comme dans Photoshop ou the GIMP (une petite précision : tel quel ce code ne fonctionne que dans le cadre d'une sous-classe d'un NSDocument et d'une appli Document-based) :

Composition des classes :
4 classes :
- DBUndoManager : va remplacer le NSUndoManager "classique" (j'ai du tout réimplémenter car je n'ai pas réussi à  surcharger correctement NSUndoManager). Ainsi, vous allez devoir créer un DBUndoManger par NSDocument

- DBUndoStack et DBUndoObject : deux classes de "bases", servent à  implémenter les comportement des undo managers, normalement vous n'aurez pas besoin d'y toucher

- DBUndoUIController : le controlleur d'interface, a connecter avec la tableView d'historique et a définir en tant que dataSource et delegate de cette tableview.
Le DBUnodUIController est une instance partagée qui se réfère au DBUndoManager du document au premier plan

Modifications supplémentaires de votre code :
Pour que ca fonctionne, il faut que le DBUndoUIController soit prévenu au changement de document. Ainsi, j'ai pondu le code suivant dans un delegate de NSApp :

<br />NSString *DBCurrentDocumentDidChange = @&quot;Current document did change&quot;;<br /><br />- (void)awakeFromNib<br />{&nbsp; &nbsp; &nbsp; <br />	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowDidBecomeMain:) name:NSWindowDidBecomeMainNotification object:nil];<br />	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(windowWillClose:) name:NSWindowWillCloseNotification object:nil];<br />}&nbsp;  <br /><br />- (void)postCurrentDocChangedNotification<br />{<br />	[[NSNotificationCenter defaultCenter] postNotificationName:DBCurrentDocumentDidChange object:[[NSDocumentController sharedDocumentController] currentDocument]];<br />}<br /><br />- (void)applicationDidBecomeActive:(NSNotification *)aNotification<br />{<br />	[self performSelector:@selector(postCurrentDocChangedNotification) withObject:nil afterDelay:FLT_MIN];<br />}<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />- (void)windowWillClose:(NSNotification *)aNotification<br />{<br />	if(![[aNotification object] isKindOfClass:[NSPanel class]]){<br />		[self performSelector:@selector(postCurrentDocChangedNotification) withObject:nil afterDelay:FLT_MIN];<br />	}<br />}<br />- (void)windowDidBecomeMain:(NSNotification *)aNotification<br />{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <br />	[[NSNotificationCenter defaultCenter] postNotificationName:DBCurrentDocumentDidChange object:[[NSDocumentController sharedDocumentController] currentDocument]];<br />}<br />



Enfin, pour finir, vous aurez besoin de rajouter dans votre controlleur (sous classe de NSDocument) le code suivant (mis avec les autres sources) et pour pouvoir fignoler le travail, ne restera plus qu'a connecter les menus Undo et Redo avec respectivement undoDocument: et redoDocument: du FirstResponder.
<br />// _undoMngr est un pointeur vers le DBUndoManager que vous avez créé<br /><br />- (DBUndoManager *)specialUndoManager<br />{<br />	return _undoMngr;<br />}<br /><br />- (void)undoDocument:(id)sender<br />{<br />&nbsp; &nbsp; if([_undoMngr canUndo]){<br />		[_undoMngr undo];<br />&nbsp; &nbsp; }<br />}&nbsp;  <br /><br />- (void)redoDocument:(id)sender<br />{<br />&nbsp; &nbsp; if([_undoMngr canRedo]){<br />		[_undoMngr redo];<br />&nbsp; &nbsp; }<br />}<br /><br />- (BOOL)validateMenuItem:(NSMenuItem *)item<br />{<br />	if([item action] == @selector(undoDocument:)){<br />		[item setTitle:[_undoMngr undoMenuItemTitle]];<br />		return [_undoMngr canUndo];<br />	}else if([item action] == @selector(redoDocument:)){<br />		[item setTitle:[_undoMngr redoMenuItemTitle]];<br />	&nbsp; &nbsp; return [_undoMngr canRedo];<br />&nbsp; &nbsp; }else{<br />		return [super validateMenuItem:item];<br />	}<br />}<br /><br />- (void)didUndo:(NSNotification *)note<br />{<br />	[self updateChangeCount:NSChangeUndone];<br />}<br /><br />- (void)didRedo:(NSNotification *)note<br />{<br />	[self updateChangeCount:NSChangeDone];	<br />}<br /><br />- (void)actionsDidChange:(NSNotification *)note<br />{<br />	int i;<br />&nbsp; &nbsp; [self updateChangeCount:NSChangeCleared];	<br /><br />	for( i = 0; i &lt; [_undoMngr undoCount]; i++ )<br />	{<br />		[self updateChangeCount:NSChangeDone];	<br />	}<br />}<br />


Voici donc le lien DrawBerry
Si vous avez des questions ou des suggestions, n'hésitez pas ...
Connectez-vous ou Inscrivez-vous pour répondre.