Αναιρέσιμες λειτουργίες

Εξετάσαμε πολλούς διαφορετικούς τρόπους για συνεισφορά ενεργειών στον πάγκο εργασίας, όμως δεν επικεντρωθήκαμε στην υλοποίηση της μεθόδου run() μιας ενέργειας. Η μηχανική της μεθόδου εξαρτάται από την εν λόγω συγκεκριμένη ενέργεια, όμως η δόμηση του κώδικα ως αναιρέσιμης λειτουργίας επιτρέπει στην ενέργεια να συμμετάσχει στην υποστήριξη αναίρεσης και ακύρωσης αναίρεσης της πλατφόρμας.

Η πλατφόρμα παρέχει ένα πλαίσιο αναιρέσιμων λειτουργιών στο πακέτο org.eclipse.core.commands.operations. Υλοποιώντας τον κώδικα μέσα σε μια μέθοδο run() για τη δημιουργία μιας IUndoableOperation, η λειτουργία μπορεί να καταστεί διαθέσιμη για αναίρεση και ακύρωση αναίρεσης. Η μετατροπή μιας ενέργειας για τη χρήση λειτουργιών είναι ξεκάθαρη, πέρα από την υλοποίηση της ίδιας της συμπεριφοράς αναίρεσης και ακύρωσης αναίρεσης.

Εγγραφή αναιρέσιμης λειτουργίας

Ξεκινούμε εξετάζοντας ένα πολύ απλό παράδειγμα. Θυμηθείτε την απλή ViewActionDelegate που παρέχεται στην πρόσθετη λειτουργία του παραδείγματος αρχείου readme. Κατά την κλήση της, η ενέργεια απλά εκκινεί ένα πλαίσιο διαλόγου που ανακοινώνει ότι εκτελέστηκε.

public void run(org.eclipse.jface.action.IAction action) {
	MessageDialog.openInformation(view.getSite().getShell(),
		MessageUtil.getString("Readme_Editor"),  
		MessageUtil.getString("View_Action_executed")); 
}
Χρησιμοποιώντας λειτουργίες, η μέθοδος run είναι υπεύθυνη για τη δημιουργία λειτουργίας που κάνει τη δουλειά που γινόταν προηγουμένως στη μέθοδο run, και την αίτηση για εκτέλεση της λειτουργίας από ένα ιστορικό λειτουργιών, ώστε να είναι δυνατή η απομνημόνευση της αναίρεσης και της ακύρωσης αναίρεσης.
public void run(org.eclipse.jface.action.IAction action) {
	IUndoableOperation operation = new ReadmeOperation(
		view.getSite().getShell()); 
	...
	operationHistory.execute(operation, null, null);
}
Η λειτουργία ενθυλακώνει την παλιά συμπεριφορά από τη μέθοδο run, καθώς και την αναίρεση και ακύρωση αναίρεσης για τη λειτουργία.
class ReadmeOperation extends AbstractOperation {
	Shell shell;
	public ReadmeOperation(Shell shell) {
		super("Readme Operation");
		this.shell = shell;
	}
	public IStatus execute(IProgressMonitor monitor, IAdaptable info) {
		MessageDialog.openInformation(shell,
			MessageUtil.getString("Readme_Editor"),  
			MessageUtil.getString("View_Action_executed"));   
		return Status.OK_STATUS;
	}
	public IStatus undo(IProgressMonitor monitor, IAdaptable info) {
		MessageDialog.openInformation(shell,
			MessageUtil.getString("Readme_Editor"),  
			"Undoing view action");   
		return Status.OK_STATUS;
	}
	public IStatus redo(IProgressMonitor monitor, IAdaptable info) {
		MessageDialog.openInformation(shell,
			MessageUtil.getString("Readme_Editor"),  
			"Redoing view action");   
		return Status.OK_STATUS;
	}
}

Για απλές ενέργειες, μπορεί να είναι δυνατή η μετακίνηση όλων των μικροεργασιών στην κλάση λειτουργίας. Στην περίπτωση αυτή, μπορεί να είναι κατάλληλη η σύμπτυξη των προηγούμενων κλάσεων ενέργειας σε μία μόνο κλάση ενέργειας με παραμέτρους. Η ενέργεια θα εκτελούσε απλά την παρεχόμενη λειτουργία όταν έφτανε η στιγμή της εκτέλεσης. Πρόκειται σε μεγάλο βαθμό για μια απόφαση σχεδίασης της εφαρμογής.

Όταν μια ενέργεια εκκινεί έναν οδηγό, τότε συνήθως η λειτουργία δημιουργείται ως τμήμα της μεθόδου performFinish() του οδηγού ή μιας μεθόδου finish() της σελίδας οδηγού. Η μετατροπή της μεθόδου finish για τη χρήση λειτουργιών είναι παρόμοια με τη μετατροπή μια μεθόδου run . Η μέθοδος είναι υπεύθυνη για τη δημιουργία και εκτέλεση μιας λειτουργίας που κάνει τη δουλειά η οποία προηγουμένως γινόταν ενσωματωμένα.

Ιστορικό λειτουργιών

Έως τώρα χρησιμοποιούσαμε ένα ιστορικό λειτουργιών χωρίς ουσιαστική εξήγηση του ρόλου του. Ας εξετάσουμε ξανά τον κώδικα που δημιουργεί τη λειτουργία του παραδείγματός μας.

public void run(org.eclipse.jface.action.IAction action) {
	IUndoableOperation operation = new ReadmeOperation(
		view.getSite().getShell()); 
	...
	operationHistory.execute(operation, null, null);
}
Τι είναι το ιστορικό λειτουργιών; Η IOperationHistory ορίζει τη διεπαφή για ένα αντικείμενο που παρακολουθεί όλες τις αναιρέσιμες λειτουργίες. Όταν ένα ιστορικό λειτουργιών εκτελεί μια λειτουργία, πρώτα εκτελεί τη λειτουργία και στη συνέχεια την προσθέτει στο ιστορικό αναιρέσεων. Οι πελάτες που επιθυμούν να αναιρέσουν ή να ακυρώσουν αναίρεση λειτουργίας, μπορούν να το κάνουν χρησιμοποιώντας το πρωτόκολλο IOperationHistory .

Το ιστορικό λειτουργιών που χρησιμοποιεί μια εφαρμογή μπορεί να ανακτηθεί με αρκετούς τρόπους. Ο πιο απλός είναι η χρήση της OperationHistoryFactory.

IOperationHistory operationHistory = OperationHistoryFactory.getOperationHistory();

Ο πάγκος εργασίας μπορεί επίσης να χρησιμοποιηθεί για την ανάκτηση του ιστορικού λειτουργιών. Ο πάγκος εργασίας ρυθμίζει το προεπιλεγμένο ιστορικό λειτουργιών και παρέχει επίσης πρωτόκολλο για πρόσβαση σε αυτό. Το ακόλουθο τμήμα κώδικα παρουσιάζει τον τρόπο λήψης του ιστορικού λειτουργιών από τον πάγκο εργασίας.

IWorkbench workbench = view.getSite().getWorkbenchWindow().getWorkbench();
IOperationHistory operationHistory = workbench.getOperationSupport().getOperationHistory();
Μόλις αποκτηθεί το ιστορικό λειτουργιών, μπορεί να χρησιμοποιηθεί για την υποβολή ερωτημάτων στο ιστορικό αναιρέσεων και ακυρώσεων αναιρέσεων, την αναζήτηση της λειτουργίας που είναι η επόμενη στη γραμμή για αναίρεση ή ακύρωση αναίρεσης ή για την αναίρεση ή ακύρωση αναίρεσης συγκεκριμένων λειτουργιών. Οι πελάτες μπορούν να προσθέσουν μια IOperationHistoryListener για να λαμβάνουν ειδοποιήσεις σχετικά με αλλαγές στο ιστορικό. Άλλο πρωτόκολλο επιτρέπει σε πελάτες να θέτουν όρια στο ιστορικό ή να ειδοποιούν τις λειτουργίες ακρόασης για αλλαγές σε συγκεκριμένη λειτουργία. Πριν εξετάσουμε το πρωτόκολλο λεπτομερώς, είναι ανάγκη να κατανοήσουμε το περιβάλλον αναίρεσης.

Περιβάλλοντα αναίρεσης

Όταν δημιουργείται μια λειτουργία, αντιστοιχείται σε ένα περιβάλλον αναίρεσης που περιγράφει το περιβάλλον χρήστη στο οποίο πραγματοποιήθηκε η αρχική λειτουργία. Το περιβάλλον αναίρεσης συνήθως εξαρτάται από την προβολή ή τη λειτουργία επεξεργασίας από την οποία προήλθε η αναιρέσιμη λειτουργία. Για παράδειγμα, οι αλλαγές που γίνονται μέσα στη λειτουργία επεξεργασίας είναι συνήθως τοπικές στη λειτουργία επεξεργασίας. Στην περίπτωση αυτή, η λειτουργία επεξεργασίας θα πρέπει να δημιουργήσει το δικό της περιβάλλον αναίρεσης και να το αντιστοιχίσει σε λειτουργίες που προσθέτει στο ιστορικό. Με αυτό τον τρόπο, όλες οι λειτουργίες που εκτελούνται στη λειτουργία επεξεργασίας θεωρούνται τοπικές και ημι-ιδιωτικές. Οι λειτουργίες επεξεργασίας ή οι προβολές που λειτουργούν σε κοινόχρηστο μοντέλο χρησιμοποιούν συχνά ένα περιβάλλον αναίρεσης που έχει σχέση με το μοντέλο που χειρίζονται. Χρησιμοποιώντας ένα πιο γενικό περιβάλλον αναίρεσης, οι λειτουργίες που εκτελούνται από μια προβολή ή λειτουργία επεξεργασίας μπορούν να είναι διαθέσιμες για αναίρεση σε άλλη προβολή ή λειτουργία επεξεργασίας που λειτουργεί στο ίδιο μοντέλο.

Τα περιβάλλοντα αναίρεσης είναι σχετικά απλά στη συμπεριφορά. Το πρωτόκολλο για IUndoContext είναι αρκετά απλό. Ο βασικός ρόλος ενός περιβάλλοντος είναι να "προσδιορίζει" μια συγκεκριμένη λειτουργία ως ανήκουσα σε αυτό το περιβάλλον αναίρεσης, προκειμένου να τη διακρίνει από λειτουργίες που δημιουργήθηκαν σε διαφορετικά περιβάλλοντα αναίρεσης. Αυτό επιτρέπει στο ιστορικό λειτουργιών να παρακολουθεί το καθολικό ιστορικό όλων των αναιρέσιμων λειτουργιών που έχουν εκτελεστεί, ενώ προβολές και λειτουργίες επεξεργασίας μπορούν να φιλτράρουν το ιστορικό από μια συγκεκριμένη πλευρά χρησιμοποιώντας το περιβάλλον αναίρεσης.

Είναι δυνατή η δημιουργία περιβαλλόντων αναίρεσης από την πρόσθετη λειτουργία που δημιουργεί τις αναιρέσιμες λειτουργίες ή η πρόσβαση σε αυτές μέσω API. Για παράδειγμα, ο πάγκος εργασίας παρέχει πρόσβαση σε ένα περιβάλλον αναίρεσης το οποίο μπορεί να χρησιμοποιηθεί για λειτουργίες σε όλο τον πάγκο εργασίας. Όπως και να ληφθούν, πρέπει να γίνεται αντιστοίχιση των περιβαλλόντων αναίρεσης όταν δημιουργείται μια λειτουργία. Τα ακόλουθα τμήματα κώδικα δείχνουν πως η ViewActionDelegate της πρόσθετης λειτουργίας του αρχείο readme μπορεί να αντιστοιχίσει ένα περιβάλλον με εύρος πάγκου εργασίας στις λειτουργίες του.

public void run(org.eclipse.jface.action.IAction action) {
	IUndoableOperation operation = new ReadmeOperation(
		view.getSite().getShell()); 
	IWorkbench workbench = view.getSite().getWorkbenchWindow().getWorkbench();
	IOperationHistory operationHistory = workbench.getOperationSupport().getOperationHistory();
	IUndoContext undoContext = workbench.getOperationSupport().getUndoContext();
	operation.addContext(undoContext);
	operationHistory.execute(operation, null, null);
}

Ποιος ο λόγος χρήσης των περιβαλλόντων αναίρεσης; Γιατί δεν χρησιμοποιούμε ξεχωριστά ιστορικά λειτουργιών για ξεχωριστές προβολές και λειτουργίες επεξεργασίας; Η χρήση ξεχωριστών ιστορικών λειτουργιών προϋποθέτει ότι κάθε προβολή ή λειτουργία επεξεργασίας διατηρεί το δικό της ιδιωτικό ιστορικό αναιρέσεων και ότι η αναίρεση δεν έχει καθολική σημασία στην εφαρμογή. Αυτό μπορεί να είναι κατάλληλο για μερικές εφαρμογές και στις περιπτώσεις αυτές κάθε προβολή ή λειτουργία επεξεργασίας δημιουργεί το δικό της ξεχωριστό περιβάλλον αναιρέσεων. Άλλες εφαρμογές μπορεί να θέλουν την υλοποίηση μιας καθολικής αναίρεσης με ισχύ στις λειτουργίες όλων των χρηστών, ανεξάρτητα από την προβολή ή τη λειτουργία επεξεργασίας από την οποία προέρχονται. Στην περίπτωση αυτή, το περιβάλλον του πάγκου εργασίας πρέπει να χρησιμοποιείται από όλες τις πρόσθετες λειτουργίες που προσθέτουν λειτουργίες στον ιστορικό.

Σε πιο πολύπλοκες εφαρμογές, η αναίρεση δεν είναι ούτε αυστηρά τοπική, ούτε αυστηρά καθολική. Αντίθετα, υπάρχει αμφίδρομη σχέση μεταξύ περιβαλλόντων αναίρεσης. Αυτό επιτυγχάνεται με την αντιστοίχιση πολλαπλών περιβαλλόντων σε μια λειτουργία. Για παράδειγμα, μια προβολή πάγκου εργασίας IDE μπορεί να χειριστεί όλο το χώρο εργασίας και να το θεωρήσει ως το δικό της περιβάλλον αναίρεσης. Μια λειτουργία επεξεργασίας που είναι ανοικτή σε συγκεκριμένο πόρο στο χώρο εργασίας μπορεί να θεωρήσει τις λειτουργίες της κατά κύριο λόγο τοπικές. Ωστόσο, οι λειτουργίες που εκτελούνται μέσα στη λειτουργία επεξεργασίας μπορεί όντως να επηρεάσουν τόσο το συγκεκριμένο πόρο, όσο και τον ευρύτερο χώρο εργασίας. (Ένα καλό παράδειγμα αυτής της περίπτωσης είναι η υποστήριξη βελτιστοποίησης δομής JDT, η οποία επιτρέπει να υπάρξουν δομικές αλλαγές σε στοιχείο Java κατά την τροποποίηση του αρχείου πρωτογενούς κώδικα). Στις περιπτώσεις αυτές, είναι χρήσιμο να υπάρχει η δυνατότητα προσθήκης περιβαλλόντων αναίρεσης στη λειτουργία, ώστε η αναίρεση να μπορεί να εκτελεστεί από την ίδια τη λειτουργία επεξεργασίας, καθώς και των προβολών που χειρίζονται το χώρο εργασίας.

Τώρα που καταλάβαμε τι κάνει ένα περιβάλλον αναίρεσης, μπορούμε να εξετάσουμε ξανά το πρωτόκολλο για IOperationHistory. Το ακόλουθο τμήμα κώδικα χρησιμοποιείται για να εκτελέσει μια αναίρεση σε κάποιο περιβάλλον:

IOperationHistory operationHistory = workbench.getOperationSupport().getOperationHistory();
try {
	IStatus status = operationHistory.undo(myContext, progressMonitor, someInfo);
} catch (ExecutionException e) {
	// handle the exception 
}
Το ιστορικό θα αποκτήσει την πιο πρόσφατη λειτουργία η οποία έχει το συγκεκριμένο περιβάλλον και θα της ζητήσει να αναιρεθεί. Άλλο πρωτόκολλο μπορεί να χρησιμοποιηθεί για να αποκτήσουμε το συνολικό ιστορικό αναιρέσεων και ακυρώσεων αναιρέσεων για ένα περιβάλλον ή για να βρούμε τι πρέπει να αναιρεθεί ή ποια αναίρεση να ακυρωθεί σε ένα συγκεκριμένο περιβάλλον. Το ακόλουθο τμήμα λαμβάνει την ετικέτα για τη λειτουργία που θα αναιρεθεί σε ένα συγκεκριμένο περιβάλλον.
IOperationHistory operationHistory = workbench.getOperationSupport().getOperationHistory();
String label = history.getUndoOperation(myContext).getLabel();

Το περιβάλλον καθολικής αναίρεσης, IOperationHistory.GLOBAL_UNDO_CONTEXT, μπορεί να χρησιμοποιηθεί για αναφορά στο ιστορικό καθολικής αναίρεσης. Δηλαδή, σε όλες τις λειτουργίες στο ιστορικό ανεξάρτητα από το συγκεκριμένο περιβάλλον. Το ακόλουθο τμήμα λαμβάνει την ιστορικό καθολικής αναίρεσης.

IOperationHistory operationHistory = workbench.getOperationSupport().getOperationHistory();
IUndoableOperation [] undoHistory = operationHistory.getUndoHistory(IOperationHistory.GLOBAL_UNDO_CONTEXT);

Όποτε μια λειτουργία εκτελείται, αναιρείται ή ακυρώνεται η αναίρεσή της χρησιμοποιώντας το πρωτόκολλο του ιστορικού λειτουργιών, οι πελάτες μπορούν να παράσχουν μια λειτουργία παρακολούθησης προόδου και κάθε πρόσθετη πληροφορία περιβάλλοντος χρήστη που μπορεί να χρειαστεί για την εκτέλεση της λειτουργίας. Αυτές οι πληροφορίες μεταβιβάζονται στην ίδια τη λειτουργία. Στο αρχικό μας παράδειγμα, η ενέργεια αρχείου readme κατασκεύασε μια λειτουργία με μια παράμετρο κελύφους που θα μπορούσε να χρησιμοποιηθεί για το άνοιγμα του πλαισίου διαλόγου. Αντί της αποθήκευσης του κελύφους στη λειτουργία, μια καλύτερη προσέγγιση είναι η μεταβίβαση παραμέτρων στις μεθόδους εκτέλεσης, αναίρεσης και ακύρωσης αναίρεσης που παρέχουν κάθε πληροφορία περιβάλλοντος χρήστη που είναι απαραίτητη για την εκτέλεση της λειτουργίας. Αυτές οι παράμετροι θα μεταβιβαστούν στην ίδια τη λειτουργία.

public void run(org.eclipse.jface.action.IAction action) {
	IUndoableOperation operation = new ReadmeOperation();
	...
	operationHistory.execute(operation, null, infoAdapter);
}
Η infoAdapter είναι μια IAdaptable που μπορεί απλά να παράσχει την παράμετρο Shell η οποία μπορεί να χρησιμοποιηθεί κατά την εκκίνηση πλαισίων διαλόγου. Το παράδειγμα λειτουργίας θα χρησιμοποιήσει αυτή την παράμετρο ως εξής:
public IStatus execute(IProgressMonitor monitor, IAdaptable info) {
	if (info != null) {
		Shell shell = (Shell)info.getAdapter(Shell.class);
		if (shell != null) {
			MessageDialog.openInformation(shell,
				MessageUtil.getString("Readme_Editor"),  
				MessageUtil.getString("View_Action_executed"));   
			return Status.OK_STATUS;
		}
	}
	// do something else...
}

Ρουτίνες χειρισμού αναίρεσης και ακύρωσης αναίρεσης

Η πλατφόρμα παρέχει τυπικές ρουτίνες χειρισμού ενεργειών μεταβλητής εμβέλειας αναίρεσης και ακύρωσης αναίρεσης που μπορούν να ρυθμιστούν από προβολές ή λειτουργίες επεξεργασίας για την παροχή υποστήριξης αναίρεσης και ακύρωσης αναίρεσης για το συγκεκριμένο περιβάλλον τους. Όταν δημιουργείται η ρουτίνα χειρισμού ενεργειών, αντιστοιχείται σε αυτήν ένα περιβάλλον, ώστε το ιστορικό λειτουργιών να φιλτράρεται με κατάλληλο τρόπο για αυτή τη συγκεκριμένη προβολή. Οι ρουτίνες χειρισμού ενεργειών φροντίζουν για την ενημέρωση των ετικετών αναίρεσης και ακύρωσης αναίρεσης για την εμφάνιση της εν λόγω τρέχουσας λειτουργίας, παρέχοντας την κατάλληλη λειτουργία παρακολούθησης προόδου και πληροφορίες περιβάλλοντος χρήστη στο ιστορικό ενεργειών, και καταργώντας προαιρετικά το ιστορικό όταν η τρέχουσα λειτουργία είναι μη έγκυρη. Για διευκόλυνση παρέχεται μια ομάδα ενεργειών που δημιουργεί τις ρουτίνες χειρισμού και τις αντιστοιχεί στις ενέργειες καθολικής αναίρεσης και ακύρωσης αναίρεσης.

new UndoRedoActionGroup(this.getSite(), undoContext, true);
Η τελευταία παράμετρος είναι μια λογική τιμή που υποδεικνύει εάν τα ιστορικά αναιρέσεων και ακυρώσεων αναιρέσεων για το συγκεκριμένο περιβάλλον πρέπει να αποδεσμευθούν όταν η τρέχουσα λειτουργία που είναι διαθέσιμη για αναίρεση και ακύρωση αναίρεσης δεν είναι έγκυρη. Η ρύθμιση αυτής της παραμέτρου έχει σχέση με το παρεχόμενο περιβάλλον αναίρεσης και η στρατηγική επικύρωσης που χρησιμοποιούν οι λειτουργίες με αυτό το περιβάλλον.

Μοντέλα αναίρεσης εφαρμογών

Προηγούμενα εξετάσαμε πώς περιβάλλοντα αναίρεσης μπορούν να χρησιμοποιηθούν για την υλοποίηση διαφορετικών ειδών μοντέλων αναίρεσης εφαρμογών. Η ικανότητα αντιστοίχισης ενός ή περισσοτέρων περιβαλλόντων με λειτουργίες επιτρέπει σε εφαρμογές να υλοποιούν στρατηγικές αναιρέσεων που είναι αυστηρά τοπικές σε κάθε προβολή ή λειτουργία επεξεργασίας, αυστηρά καθολικές σε όλες τις πρόσθετες λειτουργίες ή σε μερικά ενδιάμεσα μοντέλα . Άλλη μια απόφαση σχεδίασης η οποία περιλαμβάνει αναιρέσεις και ακυρώσεις αναιρέσεων είναι εάν κάθε λειτουργία μπορεί να αναιρεθεί ή να ακυρωθεί η αναίρεσή της οποιαδήποτε στιγμή ή εάν το μοντέλο είναι αυστηρά γραμμικό, με μόνο την πιο πρόσφατη λειτουργία να μπορεί να τύχει αναίρεσης ή ακύρωσης αναίρεσης.

Η IOperationHistory ορίζει πρωτόκολλο που επιτρέπει ευέλικτα μοντέλα αναιρέσεων, αφήνοντας ξεχωριστές υλοποιήσεις να καθορίσουν τι επιτρέπεται. Το πρωτόκολλο αναίρεσης και ακύρωσης αναίρεσης που είδαμε μέχρι στιγμής προϋποθέτει ότι υπάρχει μόνο μια προσδιορισμένη λειτουργία διαθέσιμη για αναίρεση ή ακύρωση αναίρεσης σε συγκεκριμένο περιβάλλον αναίρεσης. Παρέχεται επιπλέον πρωτόκολλο που επιτρέπει στους πελάτες να εκτελούν μια συγκεκριμένη λειτουργία, ανεξάρτητα από τη θέση της στο ιστορικό. Το ιστορικό λειτουργιών μπορεί να ρυθμιστεί ώστε να μπορεί να υλοποιηθεί το κατάλληλο μοντέλο για μια λειτουργία. Αυτό γίνεται με μια διεπαφή που χρησιμοποιείται για να προεγκρίνει κάθε αίτημα αναίρεσης ή ακύρωσης αναίρεσης πριν την αναίρεση ή την ακύρωση αναίρεσης της λειτουργίας.

Λειτουργίες έγκρισης λειτουργιών

Η IOperationApprover ορίζει το πρωτόκολλο έγκρισης αναίρεσης ή ακύρωσης αναίρεσης για μια συγκεκριμένη λειτουργία. Μια λειτουργία έγκρισης λειτουργιών εγκαθίσταται σε ένα ιστορικό λειτουργιών. Συγκεκριμένες λειτουργίες έγκρισης λειτουργιών μπορούν με τη σειρά τους να ελέγξουν όλες τις λειτουργίες για την εγκυρότητά τους, να ελέγξουν λειτουργίες μόνο για ορισμένα περιβάλλοντα ή να ενημερώσουν το χρήστη εάν προκύψουν απρόβλεπτες συνθήκες σε μια λειτουργία. Το ακόλουθο τμήμα κώδικα δείχνει πώς μια εφαρμογή μπορεί να ρυθμίσει το ιστορικό λειτουργιών για την επιβολή γραμμικού μοντέλου αναιρέσεων για όλες τις λειτουργίες.
IOperationHistory history = OperationHistoryFactory.getOperationHistory();

// set an approver on the history that will disallow any undo that is not the most recent operation
history.addOperationApprover(new LinearUndoEnforcer());

Στην περίπτωση αυτή, μια λειτουργία έγκρισης λειτουργιών που παρέχεται από το πλαίσιο, LinearUndoEnforcer, εγκαθίσταται στο ιστορικό για να αποτραπεί η αναίρεση ή ακύρωση αναίρεσης οποιασδήποτε λειτουργίας η οποία δεν είναι η πιο πρόσφατη λειτουργία με αναίρεση ή ακύρωση αναίρεσης σε όλα της τα περιβάλλοντα αναιρέσεων.

Άλλη μια λειτουργία έγκρισης λειτουργιών, LinearUndoViolationUserApprover, εντοπίζει την ίδια συνθήκη και ενημερώνει το χρήστη για το αν πρέπει να επιτραπεί στη λειτουργία να συνεχίσει. Αυτή η λειτουργία έγκρισης λειτουργιών μπορεί να εγκατασταθεί σε συγκεκριμένο τμήμα του πάγκου εργασίας.

IOperationHistory history = OperationHistoryFactory.getOperationHistory();

// set an approver on this part that will prompt the user when the operation is not the most recent.
IOperationApprover approver = new LinearUndoViolationUserApprover(myUndoContext, myWorkbenchPart);
history.addOperationApprover(approver);

Οι προγραμματιστές πρόσθετων λειτουργιών είναι ελεύθεροι να αναπτύξουν και να εγκαταστήσουν τις δικές τους λειτουργίες έγκρισης λειτουργιών για την υλοποίηση μοντέλων αναίρεσης και στρατηγικών έγκρισης ανάλογα με την εφαρμογή. Στην πρόσθετη λειτουργία, ενδείκνυται η αναζήτηση έγκρισης για την αρχική εκτέλεση μιας λειτουργίας, εκτός από την αναίρεση και ακύρωση αναίρεσης της λειτουργίας. Εάν ισχύει κάτι τέτοιο, η λειτουργία έγκρισης της λειτουργίας πρέπει επίσης να υλοποιήσει το IOperationApprover2, το οποίο εγκρίνει την εκτέλεση της λειτουργίας. Όταν σας ζητηθεί η εκτέλεση μιας λειτουργίας, το ιστορικό λειτουργίας πλατφόρμας θα αναζητήσει την έγκριση από οποιαδήποτε λειτουργία έγκρισης, η οποία υλοποιεί αυτή τη διεπαφή.

Αναίρεση και πάγκος εργασίας IDE

Είδαμε τμήματα κώδικα που χρησιμοποιούν πρωτόκολλο του πάγκου εργασίας για πρόσβαση στο ιστορικό λειτουργιών και το περιβάλλον αναίρεσης του πάγκου εργασίας. Αυτό επιτυγχάνεται χρησιμοποιώντας τη IWorkbenchOperationSupport, η οποία λαμβάνεται από τον πάγκο εργασίας. Η έννοια του περιβάλλοντος αναιρέσεων για όλο τον πάγκο εργασίας είναι αρκετά γενική. Η εφαρμογή του πάγκου εργασίας είναι αυτή που θα αποφασίσει ποια συγκεκριμένη εμβέλεια προσδιορίζεται από το περιβάλλον αναιρέσεων του πάγκου εργασίας και ποιες προβολές ή λειτουργίες επεξεργασίας χρησιμοποιούν το περιεχόμενο του πάγκου εργασίας κατά την παροχή υποστήριξης αναιρέσεων.

Στην περίπτωση του πάγκου εργασίας IDE του Eclipse, το περιβάλλον αναιρέσεων του πάγκου εργασίας πρέπει να αντιστοιχισθεί με κάθε λειτουργία που επηρεάζει τον ευρύτερο χώρο εργασίας IDE . Αυτό το περιβάλλον χρησιμοποιείται από προβολές που χειρίζονται το χώρο εργασίας, όπως η "Πλοήγηση σε πόρους".. Ο πάγκος εργασίας IDE εγκαθιστά έναν προσαρμογέα στο χώρο εργασίας για IUndoContext που επιστρέφει το περιβάλλον αναιρέσεων του πάγκου εργασίας. Αυτή η καταχώρηση με βάση μοντέλο επιτρέπει στις πρόσθετες λειτουργίες να χειρίζονται το χώρο εργασίας για να αποκτήσουν το κατάλληλο περιβάλλον αναιρέσεων, ακόμα και χωρίς εφαρμογή και δεν παραπέμπουν σε οποιαδήποτε κλάση του πάγκου εργασίας.

// get the operation history
IOperationHistory history = OperationHistoryFactory.getOperationHistory();

// obtain the appropriate undo context for my model
IUndoContext workspaceContext = (IUndoContext)ResourcesPlugin.getWorkspace().getAdapter(IUndoContext.class);
if (workspaceContext != null) {
	// create an operation and assign it the context
}

Άλλες πρόσθετες λειτουργίες ενθαρρύνονται να χρησιμοποιούν την ίδια τεχνική για την καταχώρηση περιβαλλόντων αναιρέσεων με βάση μοντέλο.