AMIGA-Magazin · Ausgabe 2/03 · Programmierung: ARexx

Aktuelles Heft 2/03

ARexx mit Magie

Im dritten Teil des Workshops geht es darum, wie man in ARexx eine Anwendung mit grafischer Benutzer-Oberfläche erstellt. »MultiTool« ist eine komplette kleine MUI-Anwendung, die Methoden der Programmierung zeigen soll.


von Martin Steigerwald

So viele Klassen:
Die Anleitund von RxMUI beschreibt alle Klassen, Funktionen und Benachrichtigungen der Bibliothek

ARexx gilt als Skriptsprache zum Automatisieren wiederholter Vorgänge. ARexx ermöglicht ARexx-fähige Anwendungen zu steuern, um das gewünschte Ergebnis zu erreichen. So kann ein Skript YAM verwenden, um automatisch eine E-Mail zu versenden, oder ein Bildverarbeitungsprogramm, um eine Bilderserie zu skalieren.
Ein ARexx-Skript kann sich aber auch selbst dem Benutzer als Anwendung mit vollständiger grafischer Oberfläche präsentieren. ARexx bietet von Haus aus keine Unterstützung für grafische Oberflächen. Allerdings gibt es eine ganze Reihe von ARexx-Funktions-Bibliotheken im Internet, die Funktionen zum Erstellen grafischer Oberflächen bieten (s. [1]).

Wir verwenden für unser Beispiel die Bibliothek »RxMUI« von Alfonso Ranieri. RxMUI erlaubt es, mit ARexx komplette MUI-Anwendungen zu programmieren. »MUIRexx« von Russell Leighton bietet ebenfalls die Möglichkeit, MUI-Oberflächen von ARexx aus anzusteuern, verwendet dabei aber nicht den Ansatz einer typischen Funktionsbibliothek. Stattdessen wird MUIRexx als Programm gestartet. Dann lässt es sich über den ARexx-Port von einem ARexx-Skript ansprechen. Mit »RxMUI« erschien es leichter, vom ARexx-Skript die Oberfläche abzufragen, etwa, ob ein bestimmter Schalter gedrückt wurde. RxMUI hat eine ausführliche, allerdings englischsprachige Anleitung (s. »So viele Klassen«).

»MultiTool« ist eine kleine Anwendung, die es erleichtert, mehrere Dateien in einem Rutsch mit einem bestimmten Programm verarbeiten zu lassen (s. »MultiTool in Aktion«). Dabei lassen sich häufig definierte Aktionen vordefinieren. Drei Beispiele sind bereits definiert: Das Entpacken eines Archives mit »xadUnFile« aus dem xadmaster-Paket, das Entpacken einer Datei mit »xfdDecrunch« aus dem xfdmaster-Paket und das Entfernen eines MacBinary-Headers mit »macwhack«. Der Anwender kann mit einem Schalter (Cycle-Gadget) einfach eine der drei Aktionen auswählen oder selbst einen Befehl und dessen Argumente in die entsprechenden Texteingabefelder eintragen. Dann gibt man ein Quell- und ein Zielverzeichnis an und klickt auf »Ausführen«, um alle Files aus dem Quellverzeichnis mit dem gewünschten Befehl zu verarbeiten.

Struktur der MUI-Anwendung:
Die Struktur von MultiTool als MUI-Anwendung ergibt sich aus den RxMUI-Objekten, die MultiTool verwendet, um die grafische Oberfläche aufzubauen.

»MultiTool« ist dabei nur ein erster Ansatz, der sich vielfältig ausbauen lässt. So ist es zur Zeit noch nicht möglich, die vordefinierten Aktionen mit einer grafischen Oberfläche zu ändern. Auch wird die Verarbeitung der einzelnen Dateien nur in einem Shell-Fenster angezeigt. Eine grafische Fortschrittsanzeige gibt es nicht. Es bleibt also viel Raum, MultiTool nach eigenen Gutdünken zu erweitern.

Objektorientiert
Das bekannte Oberflächen-System »Magic User Interface« (kurz: »MUI«) von Stefan Stuntz ist objektorientiert aufgebaut. Eine Anwendung setzt sich demnach aus mehreren Objekten zusammen. Diese Objekte haben Eigenschaften, die man verändern kann, und Methoden, die man ausführen kann.

Üblicherweise ist dies mindestens ein Anwendungs-Objekt und ein Fenster-Objekt. Das Fenster enthält in der Regel einige vom Benutzer ansteuerbare Oberflächen-Elemente wie Schalter oder Texteingabefelder. Unser Beispiel hat zusätzlich ein Pull-Down-Menü, das aus zwei Objekten besteht: Dem »menustrip«-Objekt, also der Menüleiste, in die ein »menu«-Objekt, ein Menü namens »Projekt« eingehängt wird. Dieses Menü wird direkt im Anwendungs-Objekt als Menü der Anwendung eingefügt. MUI ordnet die Oberflächen-Elemente dynamisch an und berücksichtigt dabei die verwendete Schrift ebenso wie die Fenstergröße, die der Benutzer festlegt.

Um das zu ermöglichen, werden die Positionen und Größen von Oberflächen-Elementen nicht absolut in Pixel angegeben. Stattdessen wird die Anordnung der Elemente festgelegt, indem deren Positionen zueinander definiert werden. So definiert unsere Beispiel-Anwendungen ein horizontales Objekt mit zwei Spalten. In der ersten Spalte ist jeweils ein Label, das beschreibt, worum es beim Schalter oder Eingabefeld in der zweiten Spalte geht (s. Kasten »Struktur der MUI-Anwendung»). Die Struktur von MultiTool als MUI-Anwendung ergibt sich aus dieser Objekt-Hierarchie (s. Kasten »Struktur der MUI-Anwendung«). Mit Hilfe von Benachrichtigungen (Notifies) wird die Abfrageschleife von MultiTool über Ereignisse der grafischen Oberfläche informiert. Die Ablauf-Struktur von MultiTool ergibt sich aus dem Aufbau des ARexx-Skripts: Zunächst werden im Programm einige Variablen definiert, zwei Funktionsbibliotheken geöffnet, »RxMUI« und »rexxsupport«, und die vordefinierten Aktionen bereitgestellt.

Dann wird die Prozedur »GUI« aufgerufen, um die grafische Benutzer-Oberfläche aufzubauen (engl. GUI = Graphical User Interface). Ist dies erfolgreich, wird die Prozedur »Abfragen« aufgerufen, um auf Ereignisse zu warten: Wird »Beenden« gewählt, wird MultiTool einfach beendet. Die MUI-Oberfläche wird dabei automatisch von RxMUI und MUI geschlossen und freigegeben.

Auch ein Commodity:
MultiTool wird in Exchange angezeigt und kann verborgen oder ikonfiziert werden.

Wählt der Benutzer eine andere Aktion wird die Prozedur »Aktion_aktualisieren« aufgerufen. Diese setzt den Inhalt der beiden Eingabefelder »Befehl« und »Argumente« auf die für die vordefinierte Aktion passenden Inhalte, z.B. »xadUnFile« mit den passenden Parametern für das Entpacken eines Archivs. Dabei wird mit Platzhaltern gearbeitet, die später durch Namen der Quell- und Zieldatei oder des Quell- und Zielverzeichnisses ersetzt werden: »%qz« steht für das Quellverzeichnis, »%qd" für die Quelldatei, »%zz« steht für das Zielverzeichnis und »%zd« für die Zieldatei.
Wählt der Benutzer »Ausführen« wird die Prozedur »Ausfuehren« aufgerufen. Diese holt sich Quell- und Zielverzeichnis sowie Befehl und Argumente aus der MUI-Oberfläche. Sie prüft ob Quell- und Zielverzeichnis angegeben sind und ob es zwei unterschiedliche Verzeichnisse sind.

Ist das der Fall, liest die Prozedur über showdir() von der »rexxsupport.library« eine Liste aller Dateien im Quellverzeichnis. Nun wird jede einzelne Quelldatei in einer Schleife abgearbeitet: Die Platzhalter bei den Argumenten werden durch ihre Inhalte ersetzt und dann wird der Befehl mit den Argumenten ausgeführt.
Der ausführlich dokumentierte Quelltext von MultiTool ist über 300 Zeilen lang. Sie finden MultiTool auf der Amiga-Magazin-CD, auf den Magazin-Internetseiten und im AmiNet. Wir besprechen zwei wesentliche Ausschnitte aus dem Quelltext: die Prozedur »GUI«, die die MUI-Oberfläche erstellt, und die Prozedur »Abfragen«, die die Oberfläche abfragt.

Aufbau der Oberfläche

GUI-Abfrage:
Die MUI-Oberfläche wird mit einer kleinen Schleife vom ARexx-Script abgefragt.

Die Prozedur »GUI« definiert die Oberfläche und teilt RxMUI mit, über welche Ereignisse das Skript informiert werden möchte (Listing 1). Klappt alles, wird das Fenster geöffnet und eine »1« für Erfolg zurückgegeben. Andernfalls wird eine »0« zurückgeben und das Hauptprogramm bricht mit einer Fehlermeldung ab.

Der Prozedur werden vom Hauptprogramm einige Parameter übergeben (Listing 1, Zeile 10). »aktionen« ist eine durch "|" getrennte Liste aller Aktionen wie z.B. »Datei entpachen«. Diese wird für den Auswahlschalter »Aktionen« gebraucht. »aktion.befehl« und »aktion.argumente« beinhalten die Vorgabewerte für die entsprechenden Texteingabefelder, beim Programmstart die Werte der ersten vordefinierten Aktion. »app. version« und »app.copyright« enthalten Versions- und Copyright-Informationen über MultiTool.

Zuerst wird ein Anwendungs-Objekt »anw« definiert (Zeile 12-18). Für dieses werden einige Informationen gesetzt: Der Name der Anwendung, die Versionsinfo, das Copyright usw. Die Versionsinformation und die Beschreibung können Sie sehen, wenn Sie MultiTool starten und dann im »Exchange«-Programm den Eintrag für MultiTool anwählen. MultiTool ist wie die meisten MUI-Anwendungen ein vollständiges Commodity (s. »Auch ein Commodity«)! In Zeile 20 bis 30 wird für die MUI-Anwendung ein Pull-Down-Menü definiert. Dieses wird direkt in die Menüleiste »anw.menustrip« des Anwendungsobjekts eingehängt. Das Menü heißt »Projekt« und enthält die Funktionen »Ausführen...«, »Ikonifizieren«, »Über...«, »Beenden«. Schließlich wird noch angegeben, welches das Hauptfenster der Anwendung sein soll (»anw.
SubWindow«).

RxMUI arbeitet bei der Definition von MUI-Objekten mit ARexx-Stammvariablen. Eine Stammvariable wie »anw« enthält danach Untereinträge wie «anw.description« für die Beschreibung oder »anw.menustrip« für die Menüleiste. Kann ein Objekt mehrere Unterobjekte enthalten, dann werden diese fortlaufend durchnummeriert, z.B. »gruppe.0« für das erste GUI-Element oder »gruppe.1« für das zweite GUI-Element. Als nächstes wird nun das Fenster definiert (Zeile 35-39). Als Hauptfenster bekommt es die ID »MAIN«. Sie können noch weitere Fenster definieren, z.B. als »anw.SubWindow.1« oder »anw.SubWindow.2« Beispiel ein Fenster, um beim Ausführen der definierten Aktion auf alle Dateien des Quellverzeichnisses den Fortschritt anzuzeigen, oder ein Einstellungsfenster für die vordefinierten Aktionen. Das Fenster hat den Titel »MultiTool« und enthält die Gruppe »gruppe«.

In dieser Gruppe sind nun die einzelnen Schalter definiert (Zeile 41-43). Diese sind alle Kinder der Gruppe »gruppe«. Man könnte Sie auch als »gruppe.0«, »gruppe.1« usw. schreiben. Um nicht bei jeder Änderung die einzelnen GUI-Elemente neu durchnummerieren zu müssen, empfielt es sich, die RxMUI-Funktion »child« zu verwenden, die das GUI-Element einfach hinten dranhängt. Zu jedem Schalter bis auf den »Ausführen«-Schalter gehört ein Label, das dessen Funktion beschreibt. Label und Schalter sind nebeneinander angeordnet. Dies lässt sich am besten mit einer zweispaltigen horizontalen Gruppe erreichen. Das ist so ähnlich wie eine HTML-Tabelle, das Layout der einzelnen Elemente übernimmt MUI.
Nun werden die einzelnen Label und Schalter definiert: Der Auswahl-Schalter Aktionen, die Eingabefelder Befehl und Argumente, die Eingabefelder mit Dateiauswahl-Schalter »Quellverzeichnis« und »Zielverzeichnis«, und zuletzt der Schalter »Ausführen«. Dieser hat kein Label, stattdessen wird mit »HSpace()« einfach ein horizontaler Platzhalter verwenden.

Alles dabei:
Viele mitgelieferte Beispiele erleichtern den Einstieg in die Programmierung von RxMUI.

Bei den Texteingabefeldern mit Dateiauswahl-Schalter, der beim Anklicken ein ASL-Dateiauswahl-Dialogfenster öffnet, handelt es sich um die so genannten »popasl«-Objekte. Diese werden einzeln definiert.
Damit ist die MUI-Anwendung fertig definiert und alle deren Bestandteile. Mit der Funktion NewObj("application", "anw") wird nun das Anwendungsobjekt samt aller Unter-Objekte eingerichtet (Zeile 77-78).
Doch wie erfährt das Programm von wesentlichen Ereignissen? In MUI wird das gewöhnlich durch Benachrichtungen (Notifies) geregelt. Davon definiert MultiTool auch einige (Zeile 80-103). Bei einer Benachrichtung verbindet man zwei MUI-Objekte miteinander, in der Regel das Objekt, das abgefragt werden soll, mit dem Anwendungs-Objekt, dem die Information mitgeteilt werden soll. So besagt diese Benachrichtung, dass der Anwendung die fest definierte ID »quit« mitgeteilt werden soll, wenn das Fenster »fenster« geschlossen wird (Zeile 80-82).

res=Notify("fenster","closerequest",1,"anw","ReturnID","quit")

Das heißt, dass beim Fenster »fenster« die Eigenschaft »closerequest« (Schließaufforderung) abgefragt und wenn dieses Ereignis eingetreten ist, die Methode »ReturnID« mit dem Parameter »quit« aufgerufen wird. »ReturnID« wird für festgelegte MUI-Ereignisse verwendet. Auch für den Menü-Eintrag »Projekt/Beenden« wird diese Methode mit dem Parameter »quit« festgelegt (s.Zeile 84-86).
Für eigene Ereignisse verwenden Sie stattdessen »Return« und eine eindeutige Textkennung für das Ereignis. Für den Menü-Eintrag »Projekt/Ausführen« (»m_ausfuehren«) und den Schalter »Ausführen« (»ausfuehren«) wird beidesmal die Textkennung »ausfuehren« an das Anwendungsobjekt weitergegeben. Wenn mit dem Auswahlschalter »Aktion« eine andere Aktion gewählt wird, wird »aktion« zurückgegeben. Diese Ereignisse werden dann später vom ARexx-Skript abgefragt.

Software
Name Internetadresse
macwhack AmiNet: util/conv/macwack.lha
MUIRexx AmiNet: dev/mui/MUIRexx_3_0a.lha
RxMUI AmiNet: util/rexx/rxmui.lha
xadmaster AmiNet: util/arc/xadmaster020.lha
  AmiNet: util/arc/xadmaster060.lha
xadmaster
(Entwickler-Unterlagen)
AmiNet: util/arc/xadmasterdev.lha
xfdmaster AmiNet: util/pack/xfdmaster.lha
xfdmaster
(Entwickler-Unterlagen)
AmiNet: util/pack/xfdmaster_dev.lha
Hinweis:
»xadmaster« liegt zur Zeit in Version 12 vor. Version 9 ist in AmigaOS 3.9 und Version 10 in AmigaOS 3.9 mit installiertem Boing Bag 2 enthalten.

Zusätzlich gibt es noch zwei Benachrichtungen, die von RxMUI bzw. MUI intern gehandhabt werden: »Projekt/Über...« (»m_ueber«) verwendet die Methode »About« vom RxMUI-Anwendungsobjekt »anw», um ein kleines Infofenster anzuzeigen. »Projekt/Ikonifizieren...« (»m.ikonifizieren«) setzt das Anwendungs-Objekt »anw« auf ikonfiziert. Den Rest erledigt MUI. Die Ikonfizierbarkeit von MultiTool ist schon inklusive.
Zuletzt wird das Hauptfenster der Anwendung geöffnet, damit der Benutzer auch etwas zu sehen bekommt und Eingaben machen kann (Zeile 109-110).

Die Abfragen
Die Benachrichtungen sind definiert. Doch wie wird nun vom ARexx-Skript aus die grafische Oberfläche abgefragt? Das ist sehr einfach ­ schauen Sie sich dazu die Prozedur »Abfragen« näher an (Listing 2 und »GUI-Abfrage«):

Die RxMUI-Funktion »NewHandle« handhabt dies. Ihr übergibt man als Parameter das Anwendungsobjekt und eine Stamm-Variable, die das so genannte »Handle« beinhalten soll sowie bei Bedarf eine Maske von Signalen auf die zusätzlich geprüft werden soll. MultiTool übergibt »anw« als Anwedungsobjekt, »h« als Handle und keine Signale (Zeile 8).

In die »Handle«-Stammvariable schreibt die Funktion die Information hinein, ob sich etwas ereignet (»h.EventFlag«) hat und was sich ereignet hat (»h.Event« = Ereignis) und außerdem noch, welche Benutzer-Signale empfangen wurden (»h.Signals«). Als zusätzliches Signal könnte z.B. nach der Tastenkombination »Ctrl-C« geprüft werden. Diese Funktion ist in MultiTool nicht enthalten.

Für MultiTool interessant ist das Ereignis. Die Funktion NewHandle wartet bis ein solches Auftritt oder ein Signal empfangen wurde. Das Skript fragt ab, ob »h. EventFlag« gesetzt wurde. Wenn ja, ist ein Ereignis aufgetreten. Je nach Ereignis in »h.Event« wird nun das Programm beendet, die eingestellte Aktion ausgeführt oder aber die beiden Texteingabefelder »Befehl« und »Argumente« aktualisiert, wenn im Auswahl-Schalter »Aktion« eine andere Aktion gewählt wurde.

Literatur:
[1] Die ganze Vielfalt, Martin Steigerwald, Amiga Magazin, 8/2002
[2] Schritt für Schritt, Martin Steigerwald, Amiga Magazin 11/2002

lb

 


Hauptseite © 2003 All Rights Reserved. Alle Rechte vorbehalten Franzis' Verlag GmbH
Veröffentlichung und Vervielfältigung nur mit schriftlicher Genehmigung des Verlags

Kommentare, Fragen, Korrekturen und Kritik bitte an Webmaster AMIGA schicken.
Zuletzt aktualisiert am 23. 1. 2003.