Kurs:Programmieren in Aleph/Zusammenarbeit mit Java

Eine Benutzeroberfläche

Bearbeiten

Die Erstellung grafischer Benutzeroberflächen ist für jede Programmiersprache ein Muss. Wenn Java die untergeordnete Maschine von Aleph (also der V2M) ist, ist bereits mit der "Maschinensprache" die Erstellung grafischer Elemente möglich. Natürlich werden grafische Oberflächen mit entsprechenden Mitteln wie NetBeans oder eclipse erstellt, niemand wird den Quellcode in dieser Form schreiben. Aber hier geht es um Beispiele von Aleph und grafische Oberflächen mit etwas Funktion sind sehr anschaulich für die Verwendung von Java unter Aleph. Leider fällt es gerade Anfängern schwer, grafisch orientierte Oberflächen zu erstellen. In Java sind es die vielen referenzierenden Variablen, die den Überblick erschweren. Dabei ist es prinzipiell sehr einfach die grafischen Komponenten zu verwalten. Dieses Beispiel ist das umfangreichste und schwierigste. Es werden viele Methoden aus Java-Objekten aufgerufen. Auch die Ermittlung von Objekten aus gegebenen Objekten wird benutzt. Etwas Kenntnis der Sprache Java ist also von Vorteil, um dieses Beispiel im Detail nachzuvollziehen.

Die Situation auf dem Stack

Bearbeiten

Ein wichtiges Hilfsmittel bei der Erstellung von Programmen ist die Kommentierung. Java erzeugt sogar die Dokumentation aus den Kommentaren. Aleph ist hier noch etwas altmodischer. Wesentlich für ein Command ist die Situation des Datenstacks. Weil jede Anweisung eine Funktion ist, stellt der Stack die Argumentliste dar. Jede Funktion nimmt sich genau die Elemente vom Stack, die sie benötigt und legt ihr Ergebnis wieder ab. Um hier immer informiert zu sein, hat sich ein bestimmtes Schema der Kommentierung als sehr hilfreich erwiesen, das Stackdiagramm. Dabei wird jede Zeile des ausführbaren Quelltextes mit einer "vorher-nachher"- Konstellation der Daten kommentiert. Beide werden durch "-->" voneinander getrennt. Diese Kommentierung ist zwar mühsam, aber mit etwas Routine schnell "zusammenkopiert". Ein Beispiel:

Die einfache Addition ist eine binäre Funktion, denn es wird die Summe von mindestens zwei Werten ermittelt.
+ // val1 val2 --> sum

In diesem Stil sind die Kommentare in allen Beispielen von Aleph-Programmen gehalten. Es fällt vielleicht schon lästig, immer wieder auf diese Kommentierung hingewiesen zu werden, aber es ist wirklich unverzichtbar.

Einfaches Fenster

Bearbeiten

Die Erstellung eines Fensters ohne Inhalt ist der Ansatz für die weiteren Beispiele. Bereits dieses einfache Fenster verlangt nach Funktionalität, denn der "close"-Button soll auch die Anwendung beenden. Hier gleich der Quelltext. Er kann in die Zwischenablage kopiert und in die einfache GUI kopiert werden. Danach einfach den [Start]-Button anklicken.

// Objekt eines Frame-Windows mit Titel erzeugen

"Fenster mit Aleph"  //                             --> title
"javax.swing.JFrame" // title                       --> name title
classify             // name title                  --> class title
"{String}"           // class title                 --> wrapper class title
creator              // wrapper class title         --> creator wrapper class title
build                // creator wrapper class title --> inst
dup                  // inst                        --> inst inst

// DefaultCloseOperation an Frame-Window binden

"EXIT_ON_CLOSE"                   // inst inst            --> name inst inst
swap                              // name inst inst       --> inst name inst
fetch                             // inst name inst       --> value inst
1 ndup                            // value inst           --> inst value inst
"setDefaultCloseOperation {int}"  // inst value inst      --> name inst value inst
call                              // name inst value inst --> inst
dup                               // inst                 --> inst inst

// Umfang des Frame-Windows festlegen

300                 // inst inst              --> 300 inst inst
swap                // 300 inst inst          -->  inst 300 inst
200                 // inst 300 inst          --> int inst 300 inst
swap                // 200 inst 300 inst      --> inst 200 300 inst
"setSize {int int}" // inst 200 300 inst      --> name inst 200 300 inst
call                // name inst 200 300 inst --> inst

// Frame-Window anzeigen

"show {}" // inst      --> name inst
call      // name inst -->
.S        // Stack sollte leer sein

Es wird ein JFrame-Fenster erzeugt, ohne eine einzige Variable zu verwenden. Bei pre- und postfix Notation, also bei funktionaler Programmierung, gilt: Speichere nicht was auch ermittelt werden kann! Im hier vorliegenden Fall ist jedoch bereits der Ansatz falsch. Mit GUIs verhält es sich wie mit mathematischen Formeln – sie werden von innen nach außen gelöst. Das JFrame ist praktisch die äußere Klammer einer GUI und sollte deshalb auch erst ganz am Ende der Sequenz stehen. Leider wird das Erscheinungsbild aber immer benötigt, um die einzelnen Schritte in ihren Auswirkungen zu kontrollieren. Es wird also immer auf einen Kompromiss hinauslaufen.

Die sichtbare GUI

Bearbeiten

Diese sehr einfach gehaltene GUI ist im download von Aleph vorhanden. Sie dient zwar als Benutzeroberfläche, vorrangig sollte sie aber als Beispiel für die Zusammenarbeit von Aleph und Java. Hier wird sehr detailliert vorgegangen; die Grenze zur Langeweile (hoffentlich) nicht erreicht. Zu bedenken ist jedoch, die Denkweise zur Lösung von Problemen kann sich erst ändern, nachdem das Wissen vorhanden ist.besprochen.

Der Ansatz

Bearbeiten

Zunächst werden die grundsätzlichen Schritte festgelegt. Einige der hier aufgeführten Punkte mögen trivial erscheinen, jedoch liegen bereits in diesem frühen Stadium der Entwicklung Ursachen für unerwünschte Verhaltensweisen.

  1. Es wird ein Rahmen-Fenster (JFrame) benutzt.
  2. Es wird „DefaultClose“ zum Schließen des Fensters verwendet.
  3. Der Inhalt (ContentPane) wird durch einen eigenen Container (hier ein Panel) ersetzt.
  4. Das Rahmen-Fenster übernimmt die Ausrichtung der Komponenten.
  5. Die Anzeige erfolgt unmittelbar nach dem Aufbau.

Das "main"-Programm (es ist von Aleph getrennt) muss noch über die Dateien informiert sein.

  • Alle erforderlichen Anweisungen sind in Textdateien mit dem Suffix "vvm" vorhanden.
  • Die "vvm"-Dateien sind im Verzeichnis "gui_en", relativ zum aktuellen Verzeichnis abgelegt.

Als Eingabestrom wird nur die "oberste" Datei übergeben, denn aus ihr werden weitere geladen. Der Name der "obersten" Datei ist "gui_en/baseGUI.vvm". Weil auch neue Anweisungen erstellt werden, wird vorher der Colon-Compiler aus der Datei "KernelSec.vvm" gelesen. Die folgende Klasse "aleph" ist das koordinierende Java-Programm der genanten Anforderungen.

public class aleph {
 public static void main( String[] args) {
 engine.V2M v2m = new engine.V2M();
  v2m.inp = v2m.reader( "\"KernelSec.vvm\"      load");
  v2m.process();
  v2m.inp = v2m.reader( "\"gui_en/baseGUI.vvm\" load");
  v2m.process();
 }
}

Natürlich ist die open source Datei mit allen erforderlichen Kommentaren ausgestattet. Die "main"-Methode zeigt die einzelnen Schritte. Dem Eingabestrom "inp" wird ein "reader" übergeben. Danach wird der Eingabestrom von der Methode "process()" abgearbeitet.

Der gemachte Ansatz umfasst 5 Schritte, deren Realisierung in der Datei "gui_en/baseGUI.vvm" in Form von Aleph-Sequenzen erfolgt. Diese Sequenzen werden in den folgenden Abschnitten ausführlich besprochen.

Schritt 1: Erzeugen des Rahmen-Fensters

Bearbeiten

Hier fällt der Unterschied von einfacher Instanziierung und Creation auf. Es wird eine Methode zum Aufbau des Objekts benutzt, die ein Argument verlangt. Diese Methode wird zunächst über die geforderten Argumente bestimmt und dann wird das Objekt mit "build" instanziiert.

"Aleph in use"       //                             --> title
"javax.swing.JFrame" // title                       --> name title
classify             // name title                  --> class title
"{String}"           // class title                 --> wrapper class title
creator              // wrapper class title         --> creator wrapper class title
build                // creator wrapper class title --> frame
Begriff "wrapper" stammt aus Java und bedeutet "einwickeln / verpacken". Die V2M von Aleph benutzt diese Angabe zweifach; einmal um die entsprechende Methode zu finden und dann um die Argumente auf dem Stack so zu "verpacken", wie die Methode es erwartet.

Jetzt eine Instanz der Klasse JFrame auf dem Stack vorhanden. Sie besitzt bereits einen Titel, ist aber nicht sichtbar und hat keine Angaben über das Verhalten beim Schließen.

Schritt 2: Verhalten beim Schließen

Bearbeiten

Am Anfang der Entwicklung sind kaum besondere Verhaltensweisen beim Schließen eines Fensters zu beachten. Dateien sind nicht zu aktualisieren, Threads nicht über den eigenen Weggang zu informieren, es kann einfach verschwinden.

"EXIT_ON_CLOSE"                  // frame                  --> name frame
1 ndup                           // name frame             --> frame name frame
fetch                            // frame name frame       --> value frame
1 ndup                           // value frame            --> frame value frame
"setDefaultCloseOperation {int}" // frame value frame      --> name frame value frame
call                             // name frame value frame --> frame

Hier wird einfach die "default"-Methode der Klasse über das statische Field "EXIT_ON_CLOSE" indiziert und an das Objekt delegiert.

Schritt 3: Inhalt des Fensters festlegen

Bearbeiten

Der Inhalt eines JFrames ist im sog. ContentPane vorhanden. Dieser Container wird hier einfach durch einen neuen (ein Jpanel) ersetzt. Aufbau und Inhalt dieses Panels wird in der Datei "gui_en/panel.vvm" festgelegt. Nachdem diese Datei gelesen und die enthaltenen Anweisungen bearbeitet wurden, ist auf dem Stack ein JPanel vorhanden.

"gui_en/panel.vvm" load               // frame             --> panel frame
1 ndup                                // panel frame       --> frame panel frame
"setContentPane {java.awt.Container}" // frame panel frame --> name frame panel frame
call                                  // frame panel frame --> frame

Mit der Methode "setContentPane" wird dieser "Container" zum neuen Inhalt des Fensters.

Schritt 4: Komponenten ausrichten

Bearbeiten

Der Inhalt eines Fensters unterliegt normalerweise einem umfangreichen "Layout Management". Erst nachdem alle Komponenten entsprechend dem jeweiligen Layout angeordnet wurden, stehen die Ausmaße des Fensters fest.

dup       // frame --> frame frame
"pack {}" // frame frame --> name frame frame
call      // name frame frame --> frame

Die Methode "pack()" durchläuft die gesamte Baumstruktur der Fensters und ruft für jeden Container wieder die pack-Methode auf. Dort wird dann der jeweilige Manager für das Layout des Containers bemüht. So erfolgt die Ausrichtung, wie bei der Lösung eines "Klammerterms" - von innen nach außen. Die Container stellen dabei die Klammerebenen dar.

Schritt 5: Fenster Anzeigen

Bearbeiten

Es bleibt nur noch, das aufgebaute Fenster mit der Methode "show()" anzuzeigen.

"show {}" // frame --> name frame
call      // frame -->

Weil es in diesem Beispiel aber um die Zusammenhänge geht, wird eine Ausnahme gemacht. Die gesamte Programmierung achtet auf Trennung von Anzeige und Funktionalität. Dieser Ansatz entspricht etwa der Trennung von Format und Inhalt bei modernen Textsystemen. Bis jetzt stand Format im Vordergrund. Das Wesentliche der Anwendung ist demnach der Inhalt eines Fensters. Bisher ging es nur um die Präsentation; vergleichbar mit der Suche nach einem Rahmens für ein Gemälde. Der Rahmen mag "was her machen", den Preis aber bestimmt der Inhalt. Die letzte Zeile der Datei "gui_en/baseGUI.vvm" lautet:

"gui_en/actions.vvm" load

Hier wird nach dem Aufbau des gesamten Fensters mit seinen Inhalten die Funktionalität erzeugt. Diese Position wurde gewählt, weil Desktop-Anwendungen stets einer Baumstruktur folgen (sollten). Das erzeugte Fenster ist eine solche Anwendung und seine Komponenten unterliegen einer Baumstruktur. Im Vorgriff auf die folgenden Abschnitte wird die angestrebte Struktur bereits hier gezeigt. Damit wird die Übersicht erleichtert. Außerdem werden die Komponenten deutlich, welche über Funktionalität verfügen oder davon betroffen sind.

Baum- rechtw. zu Ereignisstruktur

Aus der Kombination von Baum- und Tabellenstruktur wird deutlich, dass nur die Actions an den Positionen 7, 5 und 9, 5 Einfluss auf das JTextField an Position 4, 4 haben. Diese Darstellung hat sich für das schnelle Auffinden von Komponenten innerhalb einer Instanz komplexer Container sehr bewährt. Um im Context zu bleiben, wird hier aber der alte Weg über Variablen beschritten.

Aufgabe:

Welche Bedeutung haben die "load"-Commands?

  1. Es werden spezielle Sequenzen ausgeführt, die nicht compiliert werden.
  2. Die Sequenzen werden durch "load" automatisch compiliert.
  3. Es handelt sich um bereits compilierte Sequenzen, die nur eingebunden werden.

Der Inhalt des Fensters

Bearbeiten

Wieder wird das Erscheinungsbild in den Vordergrund gestellt, diesmal aber müssen funktionale Elemente (z.B. Buttons und Actions) berücksichtigt werden. Zu diesem Zweck muss eine Aufstellung der benötigten Komponenten gemacht werden. Eine Analyse bestehender Oberflächen hilft, die unbedingt benötigten Elemente zu bestimmen. Es ergeben sich überraschend wenige.

  1. Ein Textbereich zum Eingeben des Programms.
  2. Ein Button zur Umsetzung des Programms.
  3. Ein Button zum löschen der Eingabe.

Puristen können auf den dritten Punkt verzichten, denn bei Programmen handelt es sich immer um fehlerfreie Zeichenfolgen. Fehlerfrei ist relativ. Frei von welchen Fehlern; syntaktischen, grammatikalischen, orthographischen, semantischen oder stilistischen? Aleph besitzt keinerlei Ansprüche derartige "Fehler" zu beurteilen. Aleph "läuft" oder "läuft nicht"; der Verfasser (Programmierer) hat immer recht. Deshalb besteht ein Recht auf Irrtümer. Diese sollen schnell zu beseitigen sein und deshalb ist Punkt 3 unverzichtbar.

Zusammengefasst kann die Problematik in die Abschnitte

  • Panel bereitstellen.
  • Layout-Management festlegen.
  • Textbereich integrieren.
  • Bereich für Buttons integrieren.

Einige Punkte können wieder in mehrere Abschnitte unterteilt werden. Zuerst jedoch der Aufbau des Panels aus der Datei "gui_en/panel.vvm":

// Instanziierung


"javax.swing.JPanel" //       --> name
classify             // name  --> class
instantiate          // class --> panel


 
// Layot-Management festlegen


"java.awt.BorderLayout"  // panel      --> name panel
"gui_en/layout.vvm" load // name panel --> panel


 
// Eingabefeld im Panel positionieren


"CENTER"                    // panel                   --> name panel
"gui_en/where.vvm" load     // name panel              --> panel where panel
"gui_en/textfield.vvm" load // panel where panel       --> field panel where panel
"gui/insert.vvm" load       // field panel where panel --> panel


 
// Panel mit Buttons ins Panel


"SOUTH"                  // panel                    --> name panel
"gui/where.vvm" load     // name panel               --> panel where panel
"gui/buttpanel.vvm" load // panel where panel        --> panel panel where panel
"gui/insert.vvm" load    // button panel where panel --> panel

Die Instanziierung eines Panel-Objekts erfolgt hier über den einfachen Creator. Eine Unterteilung in Creator-Methode und "build" ist also unnötig. Nach der Instanziierung des Panels wird als Layout Management das Border-Layout für den Container (Panel) angefordert. Weil häufig in Layout-Management verwendet wird, ist hierfür die Datei "gui_en/layout.vvm" vorhanden. Diesem "Layout-Manager" werden die Container für das Eingabefeld und die Buttons übergeben.

Layout festlegen

Bearbeiten

Die Sequenz geht von den Angaben "name" (des Managers) und einem "container" aus. Bezeichnungen in den Kommentaren sollten stets die allgemeinsten sein. Diese Sequenz ist in einer eigenen Datei vorhanden, weshalb statt "panel" hier "container" verwendet wird.

1 ndup                               // name cont             --> cont name cont
swap                                 // cont name cont        --> name cont cont
classify                             // name cont cont        --> class cont cont
instantiate                          // class cont cont       --> layout cont cont
swap                                 // layout cont cont      --> cont layout cont
"setLayout {java.awt.LayoutManager}" // cont layout cont      --> nmng cont layout cont
call                                 // nmng cont layout cont --> cont

Dieser Abschnitt bringt zunächst einen Layout-Manager, über Angabe von "name", und einen Container über die Methode "setLayout(...)" zusammen. Dann brauchen nur noch die zukünftigen Komponenten des Containers dem Layout unterworfen zu werden. Bei dem hier verwendeten Manager wurde "Border"-Layout verwendet, womit die Ortsangaben der Komponenten "NORTH", "SOUTH", "EAST", "WEST" und "CENTER" sind. Für andere Manager sind natürlich andere Ortsangaben nötig.

Ort des Einfügens

Bearbeiten

Namen von Methoden oder Sequenzen sollten einem Bezug zu ihrer Aufgabe enthalten. Deshalb trägt die Sequenz zum Einfügen einer Komponente hier den Namen "gui_en/where.vvm". Hier wird vorausgesetzt, dass die Bezeichnung der Ortsangabe (Nord, Süd ...) und der Container mit dem entsprechenden Layout auf dem Stack liegen.

1 ndup         // name panel        --> panel name panel
"getLayout {}" // panel name panel  --> name panel name panel
call           // panel name panel  --> layout name panel
fetch          // layout name panel --> where panel
1 ndup         // where panel       --> panel where panel

Weil es sich bei den Ortsangaben im „BorderLayout“ um Klassenvariablen handelt, werden die Fields aus dem im Container vorhandenen Layout-Manager geholt. Mit "getLayout" wird der Manager aus dem Container ermittelt und mit "fetch" das entsprechende Field der Ortsangabe.

Einfügen von Komponenten

Bearbeiten

Auch das Einfügen von Komponenten wird aus einer Datei übernommen. Ihr Name ist "gui_en/insert.vvm". Wegen der allgemeinen Verwendbarkeit wird sie bereits an dieser Stelle besprochen. So der Bezug mit dem Layout-Management bestehen. Es wird jetzt von einer vorhandenen Komponente "comp" ausgegangen, die in den Container über die Methode "add(...)" integriert werden soll.

swap                              // comp panel where panel --> panel comp where panel
"add {String java.awt.Component}" // panel comp panel       --> name panel comp panel
call                              // name panel comp panel  --> comp panel


// Vorsicht! Die Methode add gibt die Komponente zurück.
// Deshalb noch
 
drop                              // comp panel             --> panel

Die letzte Zeile ist sehr wichtig! Weil die Methode "add(...)" stets die eingefügte Komponente zurückliefert. Alle bisher verwendeten Methoden waren vom Typ "void" und die nichtige bzw. ungültige Rückgabe wurde ignoriert. Die API-Doc von Java sollte also stets griffbereit sein.

Das Schema ist stets: "wo wird was eingesetzt". Damit ist die Integration abgeschlossen. Die gleichen Sequenzen werden sowohl für den Bereich des Textes als auch für den Bereich der Buttons verwendet.

Eingabefeld bereitstellen

Bearbeiten

Eine "JTextArea" wird in ein "JScrollPane/tt>" eingebettet. So ist es möglich Zeilen und Spalten über den sichtbaren Bereich hinaus einzugeben und mit den "Slidern" den Sichtbereich zu verschieben. Die "Slider" werden erst bei Bedarf aktiv.

"javax.swing.JTextArea" classify // --> field



// TextField in Variable ablegen


"input" variable  // field --> field
dup "input" is    // field --> field


 
// Zeichensatz des TextFields bereitstellen


"Monospaced" 0 12   // field         --> [parms] field
"gui/font.vvm" load // [parms] field --> font field


 
// Zeichensatz binden


1 ndup "setFont {java.awt.Font}" call // font field --> field


 
// Zeichen pro Zeile festlegen

 
70 1 ndup "setColumns {int}" call // field --> field


 
// Zeilenanzahl festlegen


20 1 ndup "setRows {int}" call // field --> field


 
// TextField mit ScrollBars versehen


"javax.swing.JScrollPane" // field                       --> name field
classify                  // name field                  --> class field
"{java.awt.Component}"    // class field                 --> wrapper class field
creator                   // wrapper class field         --> creator wrapper class field
build                     // creator wrapper class field --> pane

Auf eine Besprechung zur Bereitstellung des Zeichensatzes in der Datei "gui_en/font.vvm" kann wohl verzichtet werden. Wichtig ist in der Sequenz ist nur, dass die Variable "input" die JTextField-Instanz ist. Die Verwendung dieser Variablen erleichtert die Beschreibung der weiteren Punkte und erhöht die Übersichtlichkeit.

Buttons bereitstellen

Bearbeiten

Die Buttons sind in einem eigenen Panel untergebracht. So können beide Buttons als Komponenten in das große Panel integriert werden. Auf die Besprechung zur Erstellung eines Panels mit zwei Buttons wird verzichtet, denn alle wesentlichen Schritte wurden bereits gezeigt. Jeder der beiden Buttons wird in einer Variablen "abgelegt". Die Namen dieser Variablen sind "button1" und "button2". Für Aleph-Programme sind drei Variablen bereits eine erhebliche Menge. Zur besseren Übersicht sind hier noch einmal alle Variablen aufgelistet:

  • input:
Der Eingabebereich, realisiert als JTextArea.
  • button1:
Schaltfläche für die Ausführung der Anweisungen im Eingabebereich.
  • button2:
Schaltfläche zum leeren des Eingabebereichs.

Verhaltensweisen der Buttons

Bearbeiten

Wird auf einen Button geklickt, soll eine ganz bestimmte Aktion ausgeführt werden. Hierfür gibt es für Aleph eine eigene Klasse namens "vAct". Diese Klasse ermöglicht die Erstellung von (virtuelen) "Actions" und deren Bindung an Komponenten (hier Buttons). Die Formulierung des erforderlichen Programms erfolgt in der Sprache von Aleph, die Verwendung muss aber unter Java stattfinden, denn nur Java hat die Verfügungsgewalt über Listener.

Zunächst die Aufgabe des "Startknopfs":

Wenn der Knopf gedrückt wird, soll der Inhalt des Textbereichs als Sequenz von Aleph-Anweisungen angesehen und entsprechend behandelt werden. Der Text muss also der V2M zum lesen übergeben werden. Es wird der einfachste Weg gewählt, womit der Text aus der Anzeige einfach als String auf den Stack gelegt wird. Diese Aufgabe übernimmt das folgende Command namens "start":

: start
   input
   "getText {}"
   call
  ;

Die Variable "input" (siehe: "Eingabefeld bereitstellen") ist der Textbereich aus der Anzeige. Über diese Variable stehen damit auch die Methoden des Objekts zur Verfügung. Der Aufruf der Methode "getText()" legt den Text aus der Anzeige auf dem Stack ab.

Objekte der Klasse "vAct" benötigen für ihre Instanziierung folgende Argumente:

ein Command: cmnd <-- TopOfStack
aktuelle V2M: v2m
Beschriftung: label

Die Bereitstellung der beiden untersten Elemente ist am einfachsten. Ein String mit der Zeichensequenz "Start" und das Command "envionment" stellen diese Objekte bereit. Schwieriger ist es, eine Anweisung auf dem Stack abzulegen.

Wenn der Name direkt angegeben wird, führt die V2M das Command sofort aus. Es muss also ein indirekter Zugang gewählt werden. Dazu wird zunächst der Name "start" als String auf dem Stack abgelegt. Danach wird eine Anweisung mit dieser Bezeichnung über "find" gesucht.

"start" // --> name
find    // --> true cmnd

Die Anweisung wird gefunden und auf dem Stack liegt demzufolge ein true und das start-cmnd. Das Ergebnis der Suche (true) ist uninteressant, denn es war ja bekannt. Es wird einfach mit "drop" entfernt. Wichtig ist nur das (ebenfalls vorhandene) Comand. Die gesamte Sequenz für die Bereitstellung der Argumente lautet also:

"Start" envionment "start" find drop // --> cmnd v2m label

Nachdem nun die Argumente auf dem Stack liegen, steht einer Instanziierung nichts mehr im Weg. Die Vorgehensweise entspricht genau der von anderen Objekten.

"engine.vAct" classify stellt die Klasse bereit.

"{String engine.V2M engine.command}" Beschreibt die Argumente für den

creator damit

build die Instanz erzeugt und auf dem Stack ablegt.

Damit liegt auf dem Stack eine Action (vAct-Instanz) bereit, die nur noch an eine Komponente gebunden werden muss.

Actions an Komponenten binden

Bearbeiten

Weil auf dem Stack ein vAct-Objekt liegt und es sich dabei auch um eine "Action"-Instanz handelt, kann die Bindung einfach über

button1 "setAction {javax.swing.Action}" call

erfolgen. Genau die gleiche Vorgehensweise wird nun für den "clear"-Button angewendet, wobei natürlich statt des "start"-Commands ein "clear"-Command mit entsprechendem Verhaltensmuster verwendet wird.

Eine Besonderheit ist noch zu beachten. Das Command "start" gibt einen String zurück, die Anweisung "clear" legt einen leeren String ab (im Eingabefeld). Beide Commands werden von "vAct"-Instanzen verarbeitet. Alle "vAct"-Objekte verlangen einen String, der als Eingabestrom von der virtuelle Maschine V2M verarbeitet wird. Die "clear"-Anweisung soll aber den Eingabebereich leeren und keinesfalls etwas Ausfühbares bereitstellen.

: clear
   ""
   input "setText {String}" call
   input "requestFocus { }" call
   "// String muss sein!"
  ;

Es wird einfach ein Aleph-Kommentar geliefert, der von der zwar V2M zur Kenntnis genommen, aber gewiss nicht ausgeführt wird. Es könnte auch ein String aus mindestens einem Leerzeichen sein, was aber weniger aussagekräftig wäre.

Unnötiges vergessen

Bearbeiten

Im Verlaufe des Aufbaus der "GUI" wurden drei Variablen und zwei Commands definiert. Diese Objekte haben nur für die GUI Bedeutung, sind aber für die Programmierung selbst völlig unbedeutend. Trotzdem sind sie im Wörterbuch vorhanden.

Am einfachsten ist das Problem zu lösen, wenn diese Einträge einfach vergessen werden. Es genügt, das zuerst definierte Aleph-Command mit "forget" zu entfernen, denn alle später erstellten Commands werden ebenfalls entfernt. Allerdings werden sie jetzt nur aus dem Wortschatz von Aleph entfernt. Ihre Funktionalität bleibt erhalten, denn die übersetzten Sequenzen sind ja (auch) an die Komponenten der GUI (Buttons) gebunden.

"input" find drop forget

Diese Zeile ist die letzte auszuführende in diesem Beispiel. Damit können jetzt eigene Programme einfacher mit dem wichtigsten aller Hilfsmittel – "kopieren, einfügen" – erstellt werden. Die hier besprochene Minimal-"GUI" kann sehr einfach erweitert werden. Eine Möglichkeit wäre die Integration eines Ausgabebereichs in das GUI-Fenster.

Aufgabe:

Wie ist die "GUI" mit der V2M verbunden?

  1. Über den "Start"-Button, denn er stellt die Eingabe auf dem Stack bereit.
  2. Die "GUI" ist Bestandteil der V2M.
  3. Durch die Zuweisung von "v2m.reader(...)" an "v2m.inp" im Java-Programm.