4.13 DocumentGuardianViele Programme arbeiten mit Dokumenten, die der Nutzer anlegen, bearbeiten, speichern und weitergeben kann. Objekte der Klasse DocumentGuardian erleichtern Ihnen den Umgang mit solchen Dokumenten, indem Sie allgemeine Informationen, die bei der Arbeit mit Dokumenten anfallen, verwalten. Dazu zählen z.B. der Name und der Pfad zur Dokumentendatei sowie das FileHandle der offenen Datei. Außerdem können Objekte der Klasse DocumentGuardian vorhandenen Dokumente öffnen, neue Dokumente anlegen und offene Dokumente schließen. Dabei berücksichtigen sie z.B. den Dateityp und das Token, behandeln schreibgeschützte Dateien korrekt und vieles mehr. Auf diese Weise entlasten diese Objekte den BASIC-Programmierer von einer Vielzahl von Standardaufgaben. DocumentGuardian-Objekte sind dafür ausgelegt mit der Library "DocumentTools" zusammenzuarbeiten. Diese Library bietet z.B. die zur Dateiarbeit nötigen Dialogboxen wie "Öffnen" und "Speichern unter" an. Im Handbuch "Spezielle Themen", Kapitel 15, ("Implementieren eines Dokument-Interfaces") finden Sie eine ausführliche Beschreibung wie man die Arbeit mit Dokumenten unter Verwendung der DocumentTools Library und eines DocumentGuardian-Objekts organisiert. Bitte lesen Sie dort nach, wenn Sie ausführliche Beispiele oder weitergehende Erklärungen benötigen. Zur Vereinfachung kann der gesamte Dokument-Interface Code über ein R-BASIC Menu in ihr Programm eingebaut werden. Dazu verwenden Sie das Menü "Extras" -> "Code Bausteine" -> "Dokument-Interface". Dort können Sie auch festlegen, welche Teile des Dokumentinterfaces Sie unterstützen wollen, z.B. ob Sie Musterdokumente unterstützen wollen oder nicht. Im Prinzip läuft die Arbeit mit DocumentGuardian-Objekten so ab:
Abstammung:
Objekte der Klasse DocumentGuardian sind per Default nicht sichtbar (visible = FALSE). Sie können in den generic Tree eingebunden werden. Werden sie auf visible = TRUE gesetzt verhalten sie sich wie eine Group. Die unterstützen das Geometriemanagement und können Children haben. Spezielle Instance-Variablen:
Methoden:
^4.13.1 KonfigurationConfigDataDamit das DocumentGuardian seine Aufgaben, z.B. eine Datei anzulegen oder zu öffnen, erfüllen kann, benötigt es diverse Informationen. Dazu gehören der Dateityp (DOS-, GEOS-Daten- oder VM-Datei), für GEOS-Daten- und VM-Dateien das Token und einiges mehr. Außerdem arbeitet das DocumentGuardian-Objekt eng mit der "DocumentTools"-Library zusammen. Diese Library entlastet den Programmierer, indem Sie zum Beispiel die typischen Dialogboxen zum Öffnen oder "Speichern unter" von Dateien bereitstellt. Die für die Arbeit dieser Library nötigen Informationen werden ebenfalls vom DocumentGuardian-Objekt bereitgestellt.Die Instancevariable configData enthält eine Struktur, die alle für die oben genannten Zwecke erforderlichen Informationen enthält. Die Struktur ist folgendermaßen definiert: | ||||||||||||||||||||||||||||||||||||||
STRUCT DocumentConfigStruct noDocumentString$ As String(32) templateFolder$ As String(32) nameForNew$ As String(32) fileType As word token As GeodeToken creatorToken As GeodeToken matchMask$ As String(32) matchFlags As Word reserved(4) As Word End Struct | ||||||||||||||||||||||||||||||||||||||
Bedeutung der einzelnen Felder:
Für DOS-Dateien wird oft die Kombination "DOC_MATCH_TYPE + DOC_MATCH_MASK" verwendet, währen für GEOS-Daten- und VM-Dateien oft "DOC_MATCH_TOKEN" oder "DOC_MATCH_TOKEN + DOC_MATCH_CREATOR" verwendet wird. Beispiel: | ||||||||||||||||||||||||||||||||||||||
SUB DoInitDocumentGuardian(guardian as object) DIM dc as DocumentConfigStruct ' ButtonHandler kann hier oder im UI-Code gesetzt werden guardian.ButtonHandler = DocumentAndToolButtonHandler dc.noDocumentString$ = "kein Dokument" dc.templateFolder$ = "DemoTemplates" dc.nameForNew$ = "Unbenanntes Dokument " dc.fileType = GFT_DATA dc.creatorToken.tokenChars = "PHON" dc.creatorToken.manufid = 5 dc.token.manufid = 5 dc.token.tokenChars = "PHO2" ' dc.matchMask$ = "*.TXX" # nicht benötigt für GEOS-Dateien dc.matchFlags = DOC_MATCH_TOKEN guardian.configData = dc END SUB | ||||||||||||||||||||||||||||||||||||||
ButtonHandlerDie Instancevariable ButtonHandler enthält einen Handler, der von der DocumentTools-Library benötigt wird. Er muss als ButtonAction deklariert sein und wird gerufen, wenn der Nutzer einen Button im "Neu/Öffnen" Dialog anklickt. Dieser Dialog wird von der Routine DTNewOpenDialog aus der DocumentTools Library erzeugt. Weitere Informationen dazu finden Sie im Handbuch der Library.
Syntax UI-Code: ButtonHandler = <Handler>
Schreiben: <obj>.ButtonHandler = <Handler>
Beispiel: | ||||||||||||||||||||||||||||||||||||||
DocumentGuardian MyDocObj ButtonHandler = DocumentAndToolButtonHandler End Object | ||||||||||||||||||||||||||||||||||||||
^4.13.2 Verwalten von DokumentenCreateNewDocumentMit der Methode CreateNewDocument legt das DocumentGuardian Objekt ein neues Dokument entsprechend den in der Instancevariablen configData gespeicherten Werten an.
Syntax BASIC-Code: <obj>.CreateNewDocument Beispiel: | ||||||||||||||||||||||||||||||||||||||
MyDocObj.CreateNewDocument MsgBox "Die neue Datei hat den Namen: " + MyDocObj.documentName$ | ||||||||||||||||||||||||||||||||||||||
OpenDocumentMit der Methode OpenDocument öffnet das DocumentGuardian Objekt ein vorhandenes Dokument. Sollte das DocumentGuardian-Objekt noch eine Dokument-Datei offen haben wird sie ohne Nachfragen geschlossen. Die globale Variable fileError wird gesetzt (Null oder Fehlercode).
Syntax BASIC-Code: <obj>.OpenDocument "name" [, forceRO ]
"name": Dateiname der zu öffnenden Datei
forceRO: FALSE: normal öffnen (Default)
TRUE: schreibgeschützt öffnen
Beispiel: | ||||||||||||||||||||||||||||||||||||||
MyDocObj.OpenDocument "MyDoc" | ||||||||||||||||||||||||||||||||||||||
CloseDocumentMit der Methode CloseDocument schließt das DocumentGuardian Objekt das aktuell von ihm geöffnete Dokument. Ist das Dokument noch unbenannt (das Bit DOCS_UNTITLED ist gesetzt in der Instancevariablen documentState) so wird die Datei nach dem Schließen gelöscht. Für den seltenen Fall, dass Sie nicht möchten, dass unbenannte Dokumente nach dem Schließen gelöscht werden, müssen Sie FALSE als Parameter angeben. Die globale Variable fileError wird in beiden Fällen gesetzt (Null oder Fehlercode).
Syntax BASIC-Code: <obj>.CloseDocument
<obj>.CloseDocument FALSE
Beispiele: | ||||||||||||||||||||||||||||||||||||||
MyDocObj.CloseDocument MyDocObj.CloseDocument FALSE | ||||||||||||||||||||||||||||||||||||||
DocumentHandleDiese Instancevariable enthält das File-Handle der aktuell vom DocumentGuardian geöffneten Datei. Ist kein Dokument geöffnet enthält documentHandle ein NullHandle.
Syntax Lesen: <fh> = <obj>.documentHandle
<fh>: Variable vom Typ FILE
Beispiel: | ||||||||||||||||||||||||||||||||||||||
DIM fh as FILE
DIM text$
fh = MyDocObj.documentHandle
IF fh <> NullFile() THEN
text$ = FileReadLine$ ( fh )
End IF
| ||||||||||||||||||||||||||||||||||||||
DocumentName$DocumentName$ enthält den Namen der aktuell vom DocumentGuardian geöffneten Datei. Ist kein Dokument geöffnet enthält documentName$ den Text, der im Feld "noDocumentString" der Instancevariablen configData gespeichert ist.
Syntax Lesen: <stringVar> = <obj>.documentName$
<stringVar>: Variable vom Typ String
Beispiel: | ||||||||||||||||||||||||||||||||||||||
MyPrimary.Caption2$ = MyDocObj.documentName$ | ||||||||||||||||||||||||||||||||||||||
DocumentPath$DocumentPath$ enthält den Pfad zur aktuell vom DocumentGuardian geöffneten Datei. Ist kein Dokument geöffnet documentPath$ den Pfad zur zuletzt geöffneten Datei.Syntax Lesen: <stringVar> = <obj>.documentPath$ <stringVar>: String-Variable, die 200 Zeichen aufnehmen kann. Normale Stringvariablen können bis zu 128 Zeichen aufnehmen. Das ist in den meisten Fällen ausreichend, kann jedoch zu wenig sein, weil Pfade bis zu 198 Zeichen lang sein können. Beispiel: | ||||||||||||||||||||||||||||||||||||||
DIM path$(200) path$ = MyDocObj.documentPath$ MsgBox "Das Dokument liegt im Ordner '" + path$ + "'." | ||||||||||||||||||||||||||||||||||||||
documentState, SetDocumentStateDie Instancevariable documentState enthält Informationen (Flagbits) über den aktuellen Zustand des vom DocumentGuardian-Objekt verwalteten Dokuments. DocumentState enthält den Wert Null wenn kein Dokument offen ist. Folgende Bits sind definiert:
(*) Das Bit DOCS_MODIFIED wird vom DocumentGuardian-Objekt weder automatisch gesetzt noch zurückgesetzt. Es wird von der "DocumentTools" Library benötigt. Deswegen muss der Programmierer es auf dem aktuellen Stand halten. (**) Das Bit DOCS_EDIT_TEMPLATE wird vom DocumentGuardian-Objekt nicht automatisch gesetzt. Es wird benutzt um sicherzustellen, dass der nächste "Öffnen"-Dialog den Dokument-Ordner anzeigt, und nicht dem der aktuell offenen Datei (den Template-Ordner). Der Programmierer sollte es setzen, wenn er ein Muster zum Bearbeiten öffnet. Es wird beim Schließen dieser Datei automatisch zurückgesetzt. Die Instancevariable documentState kann nur gelesen werden. Um sie zu ändern verwenden Sie die Methode SetDocumentState. Sie erwartet zwei Parameter: die Bits, die zu setzen sind und die Bits, die zu löschen sind. Das vereinfacht die Verwaltung des Dokumentstatus wesentlich. SetDocumentState kann nur die Bits DOCS_MODIFIED, DOCS_UNTITLED und DOCS_EDIT_TEMPLATE ändern. Wenn kein Dokument offen ist können diese Bits nicht gesetzt werden. Syntax BASIC-Code: <numVar> = <obj>.documentState Syntax BASIC-Code: <obj>.SetDocumentState bitsToSet, bitsToClear Beispiele: | ||||||||||||||||||||||||||||||||||||||
DIM state state = MyDocumentGuardian.documentState IF state = 0 THEN MsgBox "Es ist kein Dokument offen." IF state AND DOCS_UNTITLED THEN MsgBox "Das Dokument ist neu." | ||||||||||||||||||||||||||||||||||||||
' Dokumentstatus auf "geändert" setzen MyDocumentGuardian.SetDocumentState DOCS_MODIFIED, 0 ' Dokumentstatus auf "ungeändert" setzen MyDocumentGuardian.SetDocumentState 0, DOCS_MODIFIED | ||||||||||||||||||||||||||||||||||||||
^4.13.3 ServicesHandleShutdown, HandleRestartWenn GEOS herunterfährt muss das DocumentGuardian-Objekt das aktuelle Dokument schließen und beim Wiederhochfahren muss das gleiche Dokument wieder geöffnet werden. Darum kümmern sich die Methoden HandleShutdown und HandleRestart. Diese Methoden sollten im OnExit bzw. im OnStartup-Handler des Programms gerufen werden. Im Handbuch "Spezielle Themen", Kapitel 15, ("Implementieren eines Dokument-Interfaces") finden Sie ein ausführlicheres und kommentiertes Beispiel dazu.
Syntax BASIC-Code: <obj>.HandleShutdown
<obj>.HandleRestart
Beispiel: | ||||||||||||||||||||||||||||||||||||||
SYSTEMACTION DocExitHandler
IF flags AND AF_SHUTDOWN THEN
DocumentObj.HandleShutdown
Else
! Hier Dokument ggf. Speichern und normal schließen
End IF
END ACTION
SYSTEMACTION DocStartupHandler
IF flags AND AF_RESTORE THEN
DocumentObj.HandleRestart
End IF
END ACTION
| ||||||||||||||||||||||||||||||||||||||
documentUserDataManchmal ist es wünschenswert, Dokumentdaten an einem sicheren Platz abzuspeichern, ohne sie in die Dokumentendatei zu schreiben. Zum Beispiel "überleben" globale Variablen eine Systemrestart nicht. Die Instancevariable documentUserData kann eine einzelne Strukturvariable (d.h. bis zu 3500 Byte) aufnehmen. Wie bei jeder anderen Instancevariablen von R-BASIC Objekten stehen die Daten nach einem Systemrestart automatisch wieder zur Verfügung.Eine andere Anwendung wäre, wenn Sie ein Programm schreiben, dass mit mehreren offenen Dokumenten gleichzeitig umgehen kann, wobei jedes offene Dokument sein eigenes DocumentGuardian-Objekt hat. DocumentUserData könnte dann die Dokument-spezifischen Daten enthalten. DocumentUserData ist zuweisungskompatibel mit jeder Art von Strukturvariablen. Beim Schreiben müssen Sie allerdings die Größe der Struktur extra angeben. Beim Lesen müssen Sie selbst darauf achten, dass die Strukturen kompatibel sind, R-BASIC führt weder eine Typ- noch eine Größenprüfung aus. Aber es ist sichergestellt, dass niemals mehr Bytes kopiert werden, als die Variable auf der linken Seite der Zuweisung aufnehmen kann. Es ist zulässig mehrfach hintereinander Strukturen verschiedenen Typs und verschiedener Größe in die Instancevariable zu schreiben. R-BASIC optimiert jedes Mal den verwendeten Speicher, so dass kein Platz verschwendet wird.
Syntax Schreiben: <obj>.documentUserData = <struct>, size
<struct>: Strukturausdruck beliebigen Typs
size: Größe der Struktur
Lesen: <sturctVar> = <obj>.documentUserData
<structVar>: Strukturvariable des Typs,
der beim Schreiben verwendet wurde.
Beispiel: Wir definieren eine Struktur, die Referenzen auf zwei Objekte enthält (ein View-Objekt und ein Display-Objekt), die zur Darstellung der Dokumentdaten Verwendung finden könnten. Dann definieren wir eine Strukturvariable, belegen diese und speichern die Informationen im DocumentGuardian Objekt. | ||||||||||||||||||||||||||||||||||||||
STRUCT MyObjects docView as OBJECT docDiaplay as OBJECT End Struct | ||||||||||||||||||||||||||||||||||||||
DIM ob, ob2 as MyObjects ob.docView = MyView ob.docDisplay = MyDisplay guardian.documentUserData = ob, sizeof(ob) .... ob2 = guardian.documentUserData .... | ||||||||||||||||||||||||||||||||||||||
^ |