Vorschläge zur Realisierung einer Programm-unabhängigen Undo-Funktion

Implementierung

Für die programmtechnische Umsetzung dieser Funktionen bietet es sich an, eine eigene Klasse zu konstruieren. Deren einzige Aufgabe darin besteht, die Verwaltung der Dokumentenzustände vorzunehmen.

In der von Delphi üblichen Syntax bezeichnen wir die Klasse als TReturn. Tabelle 1 liefert einen Überblick über die Attribute und Tabelle 2 über die Methoden. Hinsichtlich der Attribute wird noch der Datentyp mit angegeben.

Tabelle 1: Die Attribute der Klasse
Attribute Datentyp Hinweise
Index Integer Verwaltet den Laufindex für die Array-Variablen.
TmpFileName Array of String Speicherort für die Dateinamen der gesicherten Zustände.
Beschreibung Array of String Nimmt die Kurzbeschreibung des Zustandes auf.
Tabelle 2: Die Methoden der Klasse
Operation Hinweise
Contructor Create () Es handelt sich um den Konstruktor der Klasse. Damit wird die Klasse TReturn im Speicher erzeugt.
Destructor Destroy () Die Klasse wird wieder zerstört und aus dem Speicher gelöscht.
procedure Delete () Alle Einträge der Rückgängig-Liste werden gelöscht. Danach kann nicht mehr zu älteren Zuständen zurückgekehrt werden.
procedure Save (Text: String) Der aktuelle Arbeitsstand des Dokuments wird gespeichert.
function GetName: String Es wird der Dateiname (Zugriffsname) für die letzte gespeicherte Dokumentenversion geliefert.
function GetNameOnPosition (Position: Byte): String Es wird der Dateiname (Zugriffsname) für einen Dokumentenzustand geliefert. Der Parameter Position gibt dabei die Zahl der zurückgenommenen Schritte an.
procedure Break () Macht den letzen Speicherpunkt rückgängig.
procedure SetDokument (.) Schafft die Verbindung zwischen der Klasse TReturn und dem bestehenden Klassensystem der Anwendung.

Die weiteren Erläuterungen sollen mittels der Analyse unserer TReturn-Klasse fortgesetzt werden. Beginnen wir mit einen Blick in den Quellcode des Konstruktors. Dieser wird standardmäßig zur Erzeugung der Klasse aufgerufen (Listing 1).

Listing 1
------------------------------------------------------------------
constructor TReturn.Create(Grafik:TGrafik);
begin
   FGrf:=Grafik;
   FIndex:=-1;
   SetLength(FTmpFileName,50);
   Setlength(Beschreibung,50);
   Delete;
end;

Es ergibt sich jetzt ein Problem bezüglich der Wahl des Beispiels. Dem Konstruktor wird zur Initialisierung hier ein Objekt vom Typ TGrafik übergeben. Dieses ist natürlich nur beispielhaft, da hier die Undo-Funktion in eine Grafikapplikation eingebaut wurde. TGrafik kapselt dort ein Dokument zur Verwaltung einer Grafik. Somit verfügt die Klasse TGrafik auch über die später benötigten Methoden Save() und Load(), welche das Speichern auf Festplatte und das Laden realisieren.

Für den Einsatz von TReturn innerhalb Ihrer Applikation verwenden Sie statt der Klasse TGrafik nun diejenige Klasse, welche für die Verwaltung Ihres Dokuments zuständig ist. Kehren wir jetzt nochmals zum Konstruktor zurück. Zunächst wird der Index mit FIndex:= -1 gesetzt und damit zum Ausdruck gebracht, dass noch keine Dokumentenversion verwaltet wird. Danach werden für die Arrayvariablen TmpFileName und Beschreibung Speicher reserviert. In unserem Beispiel wird eine Grenze von 50 angegeben. Damit wird auch gleichzeitig zum Ausdruck gebracht, dass maximal 50 Dokumentenzustände verwaltet werden können. Diese Zahl korrespondiert mit der Zahl der maximal möglichen Rückgängig-Schritte und ist anpassbar.

Werfen wir noch einen Blick auf die Methode Save(), die für das Speichern eines Zustands verantwortlich ist (Listing 2).

Listing 2
------------------------------------------------------------------
procedure TReturn.Save(Text:ShortString);
var
   i:Byte;
begin
    if FIndex

Als einziges Argument wird ein String für die Kurzbeschreibung des Zustands übergeben. Hinsichtlich der Speicherung wird geprüft, ob bereits die Maximalanzahl der Rückgängig-Schritte (Dokumentenzustände) erreicht worden ist. Ist dies der Fall, wird der älteste Dokumentenzustand gelöscht und die restlichen werden um eine Position verschoben. Es erfolgt im Anschluss eine Speicherung des letzten Arbeitsschrittes. Dieses geschieht in der Quelltextzeile:

FGrf.SaveToFile(FTmpFilename[FIndex]);

Von Interesse innerhalb der Save-Methodeist noch die Frage nach dem Speicherort. Die Arbeitsdateien für unsere Undo-Funktion werden im Temp-Verzeichnis des Benutzers abgelegt. Der Kasten „Speicherung temporärer Dateien“ gibt noch einige Hinweise dazu.

Speicherung temporärer Dateien
Für die Erzeugung einer temporären Datei ist das Betriebssystem behilflich. Der Quellcode der nachfolgenden Funktion liefert als Resultat einen (eindeutigen) Namen für eine temporäre Datei zurück.

function CreateTempFileName:String;
var
   path, filename:PChar;
begin
   path:=StrAlloc(MAX_PATH+1);
   filename:=StrAlloc(MAX_PATH+1);
   GetTempPath(MAX_PATH,path);
   GetTempFileName(path,'$',0,filename);
   Result:=String(filename);
   StrDispose(filename);
   StrDispose(path);
end;

Vorteilhaft an dieser Methode ist die zentrale Ablage der temporären Dateien durch das Betriebssystem. Im Fehlerfall können nicht gelöschte Dateien hier zentral neben anderen temporären Dateien beseitigt werden.

Betrachten wir die anderen Bestanteile der Implementierung unserer Klasse in Listing 3.

Listing 3
-------------------------------------------------------------------
procedure TReturn.Delete(Index:Byte=0);
var
   i:Byte;
begin
   for i:=Index to 49 do
   begin
       if FileExists(FTmpFileName[i]) then DeleteFile(FTmpFileName[i]);
       FTmpFileName[i]:='';
       Beschreibung[i]:='';
   end;
   FIndex:=Index-1;
end;

destructor TReturn.Destroy;
begin
    SetLength(FTmpFileName,0);
    SetLength(Beschreibung,0);
    inherited Destroy;
end;

function TReturn.GetIndex: Byte;
begin
  Result:=FIndex;
end;

function TReturn.GetName: String;
begin
      Result:='';
      if FIndex

Der Inhalt von Delete() ist selbsterklärend. Innerhalb einer Schleife werden alle Dokumentenverweise ab der Indexposition gelöscht. Wird keine Position explizit angeben, werden alle Einträge gelöscht. Delete() wird damit nach jedem Undo-Vorgang ausgelöst, um den letzten Eintrag zu löschen. Mittels Destroy() wird die gesamte Klasse innerhalb des Speichers wieder freigegeben. Diese sollte beim Schließen eines Dokuments aufgerufen werden. Die Methode GetIndex() liefert die Anzahl der verwalteten Dokumentenzustände. Schließlich wird mit GetName() bzw. GetNameOnPosition() der letzte bzw. ein bestimmter Dateiname für die Ausführung eines Undo-Befehls geliefert. Die Methode SetGrafik() ist die Konkretisierung der in Tabelle 2 beschriebenen Set-Methode zur Verknüpfung der TReturn-Klasse mit der Dokumentenklasse und muss entsprechend angepasst werden.

Kommen wir nun zu einigen Hinweisen zum Einbau unserer Undo-Funktion in die Benutzeroberfläche des Programms. Üblicherweise findet sich unterhalb des Menüpunktes Bearbeiten eines Programms der Befehl Rückgängig. Dieser widerruft die zuletzt ausgeführte Benutzerinteraktion des Programms. Um dieses zu realisieren, ist eine Verknüpfung mit der Operation GetName() notwendig. Danach erfolgt ein Neuladen des Dokuments aus der temporären Datei. Dieser Befehl kann noch mit einem Button auf der Symbolleiste verbunden werden. Damit der Benutzer weitere Informationen zum Aufruf der Rückgängig-Funktion hat und damit auch ohne Umwege mehrere Aktionen zurückgenommen werden können, bietet sich die Verwendung eines Listenfeldes an. Ein Beispiel für den Einbau der Undo-Funktion in eine Benutzeroberfläche zeigt Abbildung 2.

Abb. 2: Einbau der Undo-Funktion in das Programm

Der Pfeil-Button dient dem Auslösen der Undo-Funktion für genau einen Schritt. Ebenfalls sichtbar ist die Liste mit Aktionen, die rückgängig gemacht werden können (im dargestellten Grafikprogramm handelt es sich um eine Linie, ein Rechteck und eine Bezierkurve). Für das manuelle Anlegen eines Speicherpunkts dient der daneben platzierte Button (mit der Methode TReturn.Save() verbunden). Dieses kann als Future den Bedienkomfort eines Programms erhöhen.

Veikko Krypczyk hat Betriebswirtschaft mit dem Schwerpunkt Wirtschaftsinformatik an der FernUniversität Hagen studiert. Nebenberuflich arbeitet er als freier Softwareentwickler. Wenn Sie Fragen zum Artikel oder sonstige Anmerkungen haben, dürfen Sie den Autor gerne kontaktieren. Sie erreichen ihn unter veikko2000@yahoo.de.
Kommentare

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht.