32 Version A.04.02.a
32.1 Verschlüsselung im JAVA WSI
Aus der Server-Client-Architektur der Java-Version des IDM ergibt sich die Forderung nach einer Verschlüsselung der Kommunikation zwischen Server und Client. Da die Kommunikation zwischen beiden Teilen auch über eine Internetverbindung erfolgen kann, soll mit der Verschlüsselung erreicht werden, dass geheimzuhaltende Daten, wie z. B. Passwörter nicht im Klartext übers Netz gehen.
In dem Unterverzeichnis javassl befindet sich ein Beispiel einer IDM-Anwendung, die eine Verschlüsselungssoftware für die Kommunikation benützt.
Die Java-Version des IDM besteht aus Java-Server und Java-Client. Die Kommunikation zwischen beiden erfolgt über eine TCP/IP-Verbindung ohne Verschlüsselung, siehe folgende Abbildung.
In dem Beispiel in javassl wird sowohl auf Server- als auch auf Client-Seite noch eine Verschlüsselungssoftware dazwischengeschaltet, siehe folgende Abbildung.
Als Beispiel für den Einbau einer Verschlüsselung wurde die Software C/SSL v2.1 und J/SSL v2.0 der Firma Baltimore Technologies verwendet.
Informationen unter http://www.baltimore.com/products/jssl/sslintro.html
Die C/SSL-API ist in C geschrieben und wird für die Kommunikation auf Java-WSI-Server-Seite verwendet, die J/SSL-API liegt in Java vor und wird für die Kommunikation auf Java-WSI-Client-Seite eingesetzt.
Beide Softwarepakete entsprechen der Version 3.0 von SSL und bieten Schutz gegen eine PKCS#1 Attacke.
Getestet wurde die Software unter dem Betriebssystem UNIX, Sparc Solaris 2.6
32.1.1 Funktionsweise von SSL
SSL wurde von Netscape entwickelt.
SSL (Secure Sockets Layer) ist ein Kommunikationssystem, das Geheimhaltung garantiert, wenn es mit anderen SSL-fähigen Produkten kommuniziert. SSL ist ein Protokoll, das oberhalb des TCP/IP-Protokolls und unterhalb von Top-Level-Protokollen wie HTTP läuft. Zur Überprüfung und Bestätigung der Identität der Kommunikationspartner wird asymmetrische Verschlüsselung zusammen mit Zertifikaten verwendet. Für die eigentliche Kommunikation wird symmetrische Verschlüsselung benützt. Eine SSL-Verbindung kann nur zwischen einem SSL-fähigen Client und einem SSL-fähigen Server stattfinden.
Eine genaue Beschreibung des Datenaustausches mittels SSL kann unter http://developer.netscape.com/tech/security/ssl/howitworks.html nachgelesen werden.
In dieser Dokumentation ist beschrieben, welche Schritte notwendig sind, um eine Anwendung mit dem IDM zu erstellen, die innerhalb der Kommunikation der Java-Schnittstelle des IDM eine Verschlüsselungssoftware benützt. Zum Test wurde die Software C/SSL und J/SSL von Baltimore Technologies benutzt.
32.1.2 Verschlüsselung auf Server-Seite
Um die Verschlüsselungssoftware zu benützen, muss man eine Anwendung mit dem IDM bauen. In der Funktion AppMain muss die Funktion DM_InstallWSINetHandler zur Registrierung der benutzerdefinierten Funktionen aufgerufen werden.
Weiterhin müssen benutzerdefinierte Funktionen innerhalb der Anwendung definiert werden, die die notwendigen Verschlüsselungsroutinen aufrufen. Resultatwert und Parameter der benutzerdefinierten Funktionen sind vorgegeben.
32.1.3 Die Schnittstellenfunktion DM_InstallWSINetHandler
Mit dieser Funktion der DM-Schnittstelle werden die benutzerdefinierten Funktionen, in denen die Verschlüsselungssoftware aufgerufen wird, registriert.
Diese Funktion muss in AppMain vor DM_Initialize aufgerufen werden.
Resultatwert und Parameter der benutzerdefinierten Funktionen sind vorgegeben.
Syntax
DM_Boolean DML_default DM_EXPORT DM_InstallWSINetHandler
(
DM_WSINetFunctions *wsinetfunctions,
DM_Uint Operation,
DM_Options Options
)
-> DM_ WSINetFunctions *wsinetfunctions
Struktur, die die Funktionszeiger auf die benutzerdefinierten Funktionen enthält. Sie hat folgende Form:
DM_WSINetFunctions
{
DMAcceptProc,
DM_SessionProc,
DM_ShutDownProc,
DM_OpenProc,
DM_CloseProc,
DM_SendProc,
DM_ExistsMessageProc,
DM_RecvProc,
DM_FreeWarningProc
}
Die einzelnen Funktionstypen haben folgende Form:
int <name of DM_AcceptProc function>
(int serverfd,void *cliaddr,void *addrlen,char *message)
void * <name of DM_SessionProc function>
(int clientfd,void *support,char *message)
void<name of DM_ShutDownProc function>()
int<name of DM_OpenProc function
(int *port,void **supportptr,char *message,char **warning)
int <name of DM_CloseProc function>
(void *connptr,int *clientfd,char *message)
int <name of DM_SendProc function>
(void *connptr,char *buffer,int length,char message)
int<name of DM_ExistsMessageProc function>
(void *connptr,char *message)
int <name of DM_Recv function>
(void *connptr,char *buffer,int count,char *message)
void<name of DM_FreeWarningProc function>
(char *warning)
-> DM_Uint Operation
Eine von den zwei vordefinierten Konstanten:
- DMF_RegisterHandler zum Registrieren der benutzerdefinierten Funktionen.
- DMF_WithdrawHandler zum Deregistrieren der benutzerdefinierten Funktionen.
-> DM_Options Options
Wird nicht benutzt und ist mit 0 vorzubelegen:
Rückgabewert
TRUE |
Für DMF_RegisterHandler: Funktionen konnten registriert werden. Für DMF_WithdrawHandler: Rückgabewert immer TRUE. |
FALSE |
Für DMF_RegisterHandler: Funktionen konnten nicht registriert werden. |
32.1.4 Benutzerdefinierte Funktionen
Beschreibung der einzelnen Funktionen:
-
DM_AcceptProc
Akzeptiert eine Verbindung zu einem Client.
-
DM_SessionProc
Gibt den Descriptor des Clients als Rückgabewert void * aus.
Setzt Parameter für die Client-Session.
-
DM_ShutDownProc
Nimmt Abschlussaktionen vor beim Schließen der Verbindung.
-
DM_OpenProc
Konfiguriert den Socket und öffnet ihn.
-
DM_CloseProc
Schließt die Verbindung.
-
DM_SendProc
Sendet eine Message an den Client.
-
DM_ExistsMessage
Überprüft, ob der Client eine Message geschickt hat.
-
DM_RecvProc
Liest eine Message, die vom Client geschickt wurde.
-
DM_FreeWarningProc
Gibt Speicherplatz, der in DM_OpenProc für den Parameter warning allokiert wurde, frei.
Reihenfolge des Aufrufs ist normalerweise
- DM_OpenProc function
- DM_FreeWarningProc function
- DM_AcceptProc function
- DM_SessionProc function
- DM_SendProc function, DM_Recv function, DM_ExistsMessageProc function im Wechsel
- DM_CloseProc function
- DM_ShutDownProc function
Falls eine eigene Verschlüsselung mit Hilfe der benutzerdefinierten Funktionen verwirklicht werden soll, muss beim Benützen der Parameter als Ein- und Ausgabe die vom IDM vorgegebene Reihenfolge der Aufrufe berücksichtigt werden.
32.1.5 Beispiel
Im Verzeichnis javassl ist in encode.c eine Anwendung mit dem IDM für Verschlüsselung auf Server-Seite zu finden. Es wird ein SSL-Socket auf Java-Server-Seite aufgebaut. Die Kommunikation wird mit Hilfe der Software-Pakete C/SSL und J/SSL der Firma Baltimore Technologies verschlüsselt.
32.1.5.1 Verschlüsselung auf Client-Seite
Die Verschlüsselung auf Client-Seite erfolgt über eine Java-Klasse, die einen Socket mit verschlüsselter Kommunikation aufbaut.
Der Name der Klasse ist frei wählbar und kann beim Starten des IDM auf Client-Seite mittels eines Parameters übergeben werden.
Der Name der Methode, die den verschlüsselten Socket aufbaut, muss CreateSocket sein mit folgender Syntax:
public void CreateSocket (String host, int port, boolean isapplet, URL url, String jsslpath, String certificate)
Parameter
-> host
Name des Hosts
-> port
Nummer des Ports
-> isapplet
true, wenn der Client als Applet gestartet wurde.
false, wenn der Client als Applikation gestartet wurde.
-> url
URL des Applets
-> jsslpath
String, der über den Parameter idm.jsslpath angegeben wurde.
-> certificate
String, der über den Parameter idm.certificate angegeben wurde.
Um eine IDM-Anwendung mit eigener Verschlüsselungsklasse zu bauen, muss man folgendes tun:
- Die eigene Klasse kompilieren mit javac.
- Aus dem mit dem IDM ausgelieferten jar-File die Klassen extrahieren mit dem Befehl jar –xf idm.jar. Dabei wird ein Verzeichnis idmjava angelegt, in dem Klassen gespeichert werden, und ein Verzeichnis META-INF, in dem der Manifest-File gespeichert wird.
- Die eigene kompilierte Klasse und die aus idm.jar extrahierten Klassen zu einem jar-File zusammenpacken mit dem Befehl jar –cMf <Name des neuen jar-files> <Name der eigenen Klasse> idmjava/*
- Beim Starten des Clients mit dem Befehl java müssen das Package und der Name der eigenen Klasse mittels des Parameters idm.encode angegeben werden.Mit den Parametern idm.jsslpath und idm.certificate können Strings an die Methode CreateSocket übergeben werden, siehe Kapitel „Start des Beispiels zur Verschlüsselung“.
32.1.5.2 Beispiel
idmuser/EncodeClass.java
Diese Klasse ist ein Beispiel für den Aufbau eines SSL-Sockets auf Client-Seite mit Hilfe der Software J/SSL von Baltimore Technologies. Sie befindet sich im Verzeichnis javassl/idmuser. Diese Klasse wird beim Starten des Clients der IDM-Anwendung (siehe unten) mit Hilfe des Parameters idm.encode angegeben. Der Name des Packages und der Name der Klasse sind nicht festgelegt. Allerdings muss die Verschlüsselungsklasse neben dem Konstruktor zum Aufbau des Sockets eine Methode mit dem Namen CreateSocket enthalten.
Im Beispiel ist auskommentierter Programmcode für Client authentication, d.h. Beglaubigung des Clients, enthalten. Dieser Teil des Beispiels kann verwendet werden, er wurde aber nie ausgetestet.
32.1.5.2.1 Bauen des Beispiels zur Verschlüsselung
Um das Beispiel der IDM-Anwendung, bestehend aus encode.c und idmuser/EncodeClass.java, unter UNIX zu bauen, gibt es im Verzeichnis javassl den Makefile Makefile. Für den Bau der IDM-Anwendung unter Windows muss der Makefile entsprechend angepasst werden.
Vorgehensweise
-
Anpassen der Variablen des Makefiles
-
CSSL_PATH
Pfad für das Verzeichnis, in dem die Libraries für die Verschlüsselungssoftware für den Server liegen., z.B. /cssl/debug oder /cssl/release.
-
CSSL_PATHDATA
Pfad für das Verzeichnis, in dem die Zertifikate liegen und in das Daten zwischengespeichert werden dürfen, also mit Schreibberechtigung, z.B./cssl/data.
-
CSSL_INCLUDE
Pfad für das Verzeichnis, in dem sich die Include-Files befinden.
-
JAVA_HOME
Pfad für das Home-Verzeichnis für die Java-Bibliothek.
-
SWING_HOME
Pfad für das Home-Verzeichnis für die Swing-Bibliothek.
-
JSSL_HOME
Pfad für das Verzeichnis, in dem die Verschlüsselungssoftware für den Client liegt, z.B. /jssl.
-
CLASS_NAME
Package und Name der Java-Klasse, in der die Verschlüsselung auf Client-Seite realisiert wird, z.B. idmuser/EncodeClass.
-
-
IDM_HOMEDIR
Der File IDM_HOMEDIR im übergeordneten Verzeichnis muss den richtigen Pfad für das Home-Verzeichnis des IDM enthalten.
-
Bauen mit make
Mit diesem Kommando wird ein ausführbarer Client gebaut.
Für den Server werden aus dem ausgelieferten jar-File für den IDM die Klassen extrahiert, die eigene Klasse – im Beispiel EncodeClass.java – wird kompiliert und alle Klassen inklusive der eigenen werden zu einem neuen jar-File idm_encode.jar zusammengepackt.
Voraussetzung
Das Verzeichnis, in dem dieser Bauprozess durchgeführt wird, muss Schreibberechtigung haben, da ein Unterverzeichnis mit dem Namen idmjava und ein Unterverzeichnis mit dem Namen META-INF angelegt wird.
32.1.5.2.1.1 Erzeugung von Zertifikaten
Um das gebaute Beispiel starten zu können, ist es notwendig, ein Zertifikat für den Server zu besitzen. Für eine kommerzielle Anwendung ist es unbedingt notwendig, ein Zertifikat für den Server bei einer Zertifizierungsbehörde zu beantragen.
Nur zu Testzwecken können Schlüssel und Zertifikate lokal mit entsprechender Software erzeugt werden. Dafür kann das von Baltimore Technologies mit der C/SSL-Software ausgelieferte UNIX-Shell-Script makecerts.sh oder das Script makecerts.bat für Windows benützt werden.
32.1.5.3 Start des Beispiels zur Verschlüsselung
-
Start des Servers
cd javassl
encode <Optionen> <Dialogfile>
Mit diesem Befehl wird der Server gestartet. Die Optionen sind dieselben wie beim Starten des Java-Servers mit dem Befehl idmjava.
Zum Testen kann der Dialogfile IDM_HOMEDIR/lib/IDM/bestelldienst.idm verwendet werden.
-
Start des Java-Clients als Applikation
cd demos/javassl
java –classpath ./idm_encode.jar:<JAVA_HOME>:<SWING_HOME>:<JSSL_HOME>/applet/jssl.jar:<JSSL_HOME>/applet/jcrypto.jar
<Optionen>
-Didm.encode=<Package . Name der Verschlüsselungsklasse>
-Didm.jsslpath <Pfad für Zertifikat>
-Didm.certificate <Name des Zertifikates>
idmjava.idm
Mit diesem Befehl wird der Client – die Klasse idmjava.idm - gestartet.
JAVA_HOME, SWING_HOME, JSSL_HOME haben dieselbe Bedeutung wie die Variablen im Makefile Makefile für den Bau des Beispiels, siehe oben.
Die Optionen <Optionen> sind dieselben wie beim Starten des Dialog Manager Java-Clients.
Die Option:
- idm.encode gibt den Pfad der Klasse an, die die Verschlüsselung erledigt. Wird die Klasse nicht gefunden, wird ein unverschlüsselter Socket aufgebaut, Beispiel für diesen Parameter idm.encode=“idmuser.EncodeClass“.
-
idm.jsslpath gibt den Pfad des Verzeichnisses an, in dem sich die Zertifikate und andere von der Verschlüsselungssoftware zwischengespeicherte Daten befinden, Beispiel /cssl/data.
Achtung
Dieser Pfad muss auf dasselbe Verzeichnis zeigen wie CSSL_PATHDATA im Makefile Makefile.
- idm.certificate gibt den Namen des Zertifikat-Files an, Beispiel caCerts.pem.
Wenn die Kommunikation zwischen Client und Server verschlüsselt ist, erscheint nach dem Start des Clients die Meldung Encoded connection auf dem Bildschirm.
-
Start des Java-Clients als Applet
Auf dem Web-Server müssen sich folgende Files befinden:
- HTML-Seite, z.B. idmapplet.html (mit Veränderungen, siehe unten)
- caCerts.pem aus C/SSL von Baltimore Technologies oder andere Identitätsfiles
- idm_encode.jar
- jcrypto.jar aus der Subdirectory applet der Software J/SSL von Baltimore Technologies
- jssl.jar aus der Subdirectory applet der Software J/SSL von Baltimore Technologies
Der <APPLET>-tag in der HTML-Seite sieht genauso aus wie beim Dialog Manager Java-Client mit folgenden Ausnahmen:
ARCHIVE=idm_encode.jar; jcrypto.jar; jssl.jar
<PARAM NAME =“idm.encode“ VALUE=“Package . Name der Verschlüsselungsklasse“>
<PARAM NAME =“idm.jsslpath“ VALUE=“Pfad für Zertifikat“>
<PARAM NAME =“idm.certificate“ VALUE=“Name des Zertifikates“>
Die Bedeutung der Parameter ist dieselbe wie beim Starten des Clients als Applikation.
-
Kommando, um Server und Client als Applikation zu starten
Um Java-Server und Java-Client mit verschlüsselter Kommunikation zu starten, kann man das Kommando make run verwenden.
Um Java-Server und Java-Client mit normaler, also unverschlüsselter Kommunikation zu starten, kann man das Kommando make normal verwenden.
32.2 Änderungen bei der Objektreferenzierung
Dieses Kapitel beschäftigt sich mit der Beziehung zwischen Objekten und ihren Bezeichnern sowie der Referenzierung von Objekten.
32.2.1 Hierarchie
Der IDM verwaltet Objekte eines Moduls hierarchisch. An oberster Stelle steht dabei das in der Datei definierte Modul. Importierte Objekte sind für das importierende Modul hierarchisch unterhalb des Imports gegliedert.
Beispiel: Folgendes Modul
module M => Hierarchie
export model pushbutton MPb {} M
export window Wi { +-MPb
export MPb Pb {} +-Wi
MPb Pb2 {} +-Pb
} +-Pb2
wird von einem Dialog verwendet. Rechterhand ist die Hierarchie der zugreifbaren Objekte aufgezeigt.
dialog D => Hierarchie
import I “m.if”; D
window Wi2 +-I
{ | +-MPb
MPb Pb {} | +-Wi
} | +- Pb
+-Wi2
+-Pb
32.2.2 Bezeichner
Jedes Objekt in einem Modul besitzt einen symbolischen Namen, einen Bezeichner. Der Bezeichner ist entweder durch den Anwender gesetzt worden oder vom Modell geerbt (Ausnahmen siehe Kapitel „Geerbte Bezeichner und Modularisierung“).
In der gleichen Hierarchieebene (Objekte mit dem gleichen Vater) können Objekte mit dem gleichen Bezeichner zwar existieren, es darf aber nur einer gesetzt sein (wird vom IDM sichergestellt). Ausnahmen, Problemstellen und Fehler siehe auch Kapitel „Hinweise auf Problemstellen und Probleme der Vorgängerversionen“ und „Bekannte Fehler/Probleme des IDM“.
Der Unterschied zwischen einem gesetzten und einem geerbten Bezeichner ist die Referenzierbarkeit. Ein geerbter Bezeichner muss durch einen Pfad referenziert werden, bei einem gesetzten eindeutigen Bezeichner kann dies auch nur durch den Bezeichner selbst geschehen.
dialog D
model pushbutton MPb {} // Bezeichner MPb ist gesetzt, verweist auf Modell
window Wi {
child MPb Pb1 {} // Gesetzter Bezeichner
child MPb {} // Vom Modell geerbt, nur über Pfad referenzierbar
}
window Wi2 {
child pushbutton Pb1 {} // Gesetzter Bezeichner, Pb1 ist nun mehrdeutig
child MPb Pb2 {} // Gesetzter Bezeichner
child MPb Pb2 {} // Nicht möglich, da auf gleicher Hierarchieebene.
// Warnung wird erzeugt, dass der Bezeichner nicht
// gesetzt werden kann => man erhält den
// geerbten Bezeichner MPb.
child MPb {}
}
on dialog start {
MPb.text:=“Ok”; // Bezeichner eindeutig, ergibt Modell
Wi.MPb.text:=“Okay”; // Obj. mit geerbtem Bezeichner (Pfad verwenden)
Pb1.text:=“Exit”; // Erzeugt einen Fehler da Pb1 mehrdeutig ist
Wi.Pb1.text:=“Exit”; // Eindeutiger Zugriff über Pfade möglich
Wi2.Pb1.text:=“Beenden”;
Wi2.Pb2.text:=”Start”;// Zugriff auf ersten Pb2
Wi2.MPb.text:=”Stop”; // Zugriff auf Objekt mit nicht setzbarem Bez.
Wi2.MPb:[2].text:=”Aus”; // Zugriff auf 2. Obj. mit gleichem Bezeichner
exit();
}
Nicht nur Objekte werden durch einen Bezeichner benannt, sondern auch benutzerdefinierte Attribute. Allerdings kann ein Attribut nicht referenziert werden, sondern es kann nur auf seinen Inhalt zugegriffen werden. Die Regel „In einer Hierarchieebene darf ein Bezeichner nur einmal gesetzt sein“ schließt nicht nur Kindobjekte sondern auch Attribute und Methoden mit ein!
dialog D
window Wi {
integer Pb := 123;
// pushbutton Pb {} // FEHLER – Bezeichner existiert schon an Wi
}
window Wi2 {
pushbutton Pb {} // Keine Mehrdeutigkeit mit Attribut .Pb an Wi
}
on dialog start {
print Pb; // eindeutig das Objekt Wi2.Pb
print Wi.Pb; // Zugriff auf den Wert des Attributes .Pb
print Wi2.Pb; // Referenzierung des Kindobjektes
exit();
}
Das Modularisierungskonzept des IDM beschränkt nur die Referenzierungen von Objekten von außen, nicht den Zugriff auf benannte Attribute und Methoden. Aus diesem Grund können/müssen Attribute nicht exportiert werden.
32.2.3 Eindeutigkeit und Mehrdeutigkeit
Der Bezeichner des Moduls ist immer eindeutig. Mehrdeutigkeit besteht, wenn mehrere Objekte in der Hierarchie (gemäß „Hierarchie“ auch importierte Objekte) den gleichen Bezeichner gesetzt haben.
module M // M ist immer eindeutig das Modul
export function string Func(integer); // Im Modul eindeutig
export window Wi { // Wi ist eindeutig
export pushbutton Pb {}
}
export window Wi2 { // Wi2 nach außen eindeutig
export pushbutton Pb {} // Pb schon im Interface mehrdeutig
window Wi2 {} // Wi2 im Modul mehrdeutig
}
on module start {
print Func(987);
M.Wi2.Wi2 := “Wi2 privat”; // Zugriff auf Wi2 nur über Pfad
}
Besteht eine Mehrdeutigkeit, so können die Objekte mit mehrdeutigen Bezeichnern durch eindeutige Pfade referenziert werden. Das muss in diesem Beispiel für den Pushbutton Pb der Fenster Wi und Wi2 und WiMain geschehen.
dialog D // D ist immer eindeutig der Dialog
import I “m.if”; // I ist eindeutig
export function integer Func(string); // Func ist mehrdeutig
window WiMain { // WiMain ist eindeutig
pushbutton Pb {} // Pb ist mehrdeutig(1.Pb aus import)
}
on dialog start {
print D.Func(“Hello”); // Zugriffe auf Func über Pfad
print I.Func(123);
WiMain.Pb:=”Ok”; // Zugriff über Pfad, da Pb mehrdeutig
Wi.title:=”Wi”; // Zugriffe nur über Bezeichner
Wi.Pb:=”Ok”;
Wi2:=”Wi2”;
// Pb.text := “PB”;
// FEHLER: Mehrdeutiger Zugriff, auskommentiert, da Fehlermeldung kommen
// wuerde und Dialog nicht ladbar wird.
exit();
}
32.2.4 Referenzierung und Referenzierungsfehler
Innerhalb eines Moduls ist ein Zugriff, z.B. in Regeln oder bei der statischen Instanziierung, auf benannte Objekt durch deren Bezeichner oder durch einen Pfad möglich. Referenzierbar in diesem Sinne sind aber nur Objekte innerhalb des Moduls bzw. importierte Objekte.
Ein Pfad ist dabei eine Kette von Bezeichnern, angefangen von einem eindeutigen Bezeichner (z.B. durch den Modul-Namen). Ist in einer Hierarchieebene ein Bezeichner mehrfach verwendet worden so ist der Zugriff auf die Objekte mit geerbtem Bezeichner durch ein Suffix der Form „:[I]“ möglich, wobei 1<I<A (A=Anzahl Objekte mit gleichem Bezeichner & Vater) ist. Grundsätzlich kann aber auch ein eindeutig bezeichenbares Objekt mit einem Pfad referenziert werden.
Pfade werden erst am Ende des Ladevorganges eines Moduls aufgelöst. Stimmt der Bezeichner nicht, erhält man eine Fehlermeldung in der Form „Cannot Resolve...“.
Ist ein Bezeichner oder der erste Bezeichner eines Pfades mehrdeutig, so erhält man einen Hinweis auf die Mehrdeutigkeit mit „Cannot Resolve ... Label is not unique“.
Bei solchen Fehlermeldungen muss zuerst der Fehler durch Richtigstellung des Bezeichners oder durch Auflösung der Mehrdeutigkeit mittels eindeutigem Pfad korrigiert werden.
Beim Schreiben eines Dialoges/Moduls, z.B. aus dem Editor heraus oder beim Binärformat, wird immer der kleinste eindeutige Pfad herausgeschrieben/verwendet.
Neben diesen absoluten Pfaden ist es auch möglich relative Pfade, die z.B. vom this-Objekt oder einer lokalen Variablen oder einem Parameter ausgehen, anzugeben. Die Auflösung dieser Pfade kann erst zur Ausführungszeit geschehen. Insofern kann beim Ladevorgang keine Fehlermeldung oder Warnung für solche Pfadangaben gebracht werden, da sie u.U. erst zur Laufzeit gültig sind.
dialog D
model pushbutton MPb {}
window Wi {
pushbutton Pb {}
MPb Pb2 {}
}
window Wi2 {
MPb Pb2 {}
MPb {} // Erhält geerbten Namen MPb vom Modell
MPb {
record R1 {}
}
checkbox {} // Erhält geerbten Default-Namen CHECKBOX
}
on dialog start {
Wi.title:=”Wi”; // Zugriff über eindeutigen Bezeichner
D.Wi.title:=”WI”; // Ebenso Zugriff über Pfad möglich
D.WI.title:=”WI”; // FEHLER – Kann nicht aufgelöst werden!
this.Wi.title:=”wi”;// Relativer Zugriff, Auflösung zur Laufzeit
this.WI.title:=”WI”;// Relativer Zugriff, Semantisch Falsch, aber Ladbar.
Wi.Pb2.text:=”Ok1”; // Pfad notwendig da mehrdeutig
D.Wi2.Pb2.text:=”Ok2”; // Pfad ist übereindeutig, D kann man weglassen
Wi2.MPb.text:=”Ok1”;// Zugriff
exit();
}
32.2.5 Geerbte Bezeichner und Modularisierung
Wenn exportierte Objekte einen geerbten Bezeichner haben, so wird normalerweise diese „Vererbung“ auch nach außen in die importierenden Module getragen. dass heißt konkret, dass ein exportiertes Objekt mit geerbtem Bezeichner nur durch einen Pfad referenziert werden kann.
Nun kann nach außen hin diese „Vererbung“ des Bezeichners gestoppt werden, indem das Modell des exportierten Objektes nicht ebenso vom Modul exportiert wird. Das hat nun aber zur Folge das solch ein exportiertes Kind ebenfalls eine Referenzierung aufweist und damit sofort eine Mehrdeutigkeit besteht, da Modell und Kind den gleichen Bezeichner haben und unterschiedliche Objekte referenzieren.
Diese Konstellation ist im folgenden Modul mit dem Modell MPb und dessen Instanzierungen als hierarchische Kinder nachgestellt.
module M
export model pushbutton MPb {}
export model radiobutton MRb {}
model checkbox MCb {}
export model groupbox MGb {
child MPb {} // #1
export child MPb {} // #2
export child MRb {}
}
export model MGb2 {
export .MPb {} // Damit wird ist #1 gemeint
export child MCb {}
}
Die Auswirkungen, dass das MPb zwar innerhalb des Moduls, aber nicht nach außen hin eindeutig ist, wird aber erst in der Verwendung zu erkennen. Am Kind MCb wird gezeigt, dass ein Objekt mit einem geerbten Bezeichner nach außen hin einen „gesetzten“ Bezeichner besitzt und damit über seinen Namen ansprechbar wird.
dialog D
import I “m.if”;
on dialog start
{
print MRb; // Eindeutig da exportiertes Kind MGb.MRb einen geerbten
// Bezeichner hat (da ja das Modell ebenfalls exportiert ist)
// print MPb; FEHLER – Mehrdeutig da Bezeichner MPb auch MGb2.MPb
// referenzier da dessen Modell nicht exportiert ist.
print I.MPb; // Referenziert das Modell
print MGb.MPb; // Referenziert #2 vom Modell MGb
print MGb2.MPb; // Referenziert #1 vom Modell MGb2
print MCb; // Referenziert Kind von MGb2 absolut trotz des geerbten
// Bezeichners, da das Modell nicht exportiert wurde.
exit();
}
Es ist grundsätzlich sinnvoll, exportierten Kindern einen Namen zu geben, der sich vom Modell unterscheidet, um den dargelegten Problematiken aus dem Weg zu gehen.
32.2.6 Exportierte Imports
Imports, die wieder exportiert werden erfahren eine Sonderbehandlung. Die Bezeichner dieser Imports werden nach außen hin wie geerbte Bezeichner behandelt. Zusätzlich erhält ein importierendes Modul alle exportierten Imports der importierten Module direkt unterhalb des Moduls/Dialoges.
Ziel ist es, Import nicht als Hierarchie erscheinen zu lassen sondern alle direkt als „Kinder“ des Dialoges, selbst wenn sie über „export import“ aus einem importierten Modul stammen.
Folgendes Beispiel veranschaulicht die Situation.
module M1
export import I2 “m2.if”;
export model pushbutton MPb {}
M1 Exportiert ebenso die Objekte aus M2.
module M2;
export model window MWi {}
Im M1 importierenden Dialog ist ein Zugriff auf die exportierten Objekte aus M2 ebenfalls möglich.
dialog D
import I1 “m1.if”;
MWi Wi { MPb {} }
window I2 {} // WARNUNG – Bezeichner kann nicht gesetzt werden,
// da durch I1 der Bezeichner I2 schon als
// import I2 unterhalb des Dialoges herkommt.
on dialog start {
print I1; // Referenziert den Import D.I1, Bezeichner I1 ist eindeutig
print I1; // Referenziert den Import D.I2, Bezeichner I2 ist eindeutig
print D.I1; // Referenziert den Import I1
print D.I2; // Referenziert den Import I2
print I1.I2 // Referenzierung über Pfad ebenfalls möglich
exit;
}
32.2.7 Überlagerung durch lokale Bezeichner
Innerhalb einer Regel überlagern Bezeichner von lokalen Variablen und Parametern die Objekt-Bezeichner und unterbinden somit die Mehrdeutigkeit.
dialog D
window W {}
rule void Rule(object W) {
variable integer D:=123;
print “D=”+D;
print “W=”+W;
}
on dialog start {
Rule(D); // => Ausgabe “D=123”
exit(); // “W=D”
}
32.2.8 Hinweise auf Problemstellen und Probleme der Vorgängerversionen
Folgenden Hinweise sollen zum Erkennen & Vermeiden von Problemstellen in vorhandenen Dialogen helfen. Die Vorgängerversionen des IDM hatten folgende Problemstellen:
- Funktionen können mehrdeutig definiert werden
- Mehrdeutigkeiten werden nicht erkannt. Bei Mehrdeutigkeiten wird die erste Referenzierung aus dem Modul/Dialog genommen.
- Einlesereihenfolge spielt eine Rolle.
- Fehlerhaftes Herausschreiben mit –writedialog: Objektreferenzierungen werden nicht eindeutig herausgeschrieben. Wegen Punkt 4 kommt, selbst wenn da Einlesen möglich ist, u.U. etwas anderes heraus.
Beispiel
dialog D
function string F1();
function integer F1(); // wurde noch mit A.04.01.c akzeptiert
window Wi {
groupbox Gb {
pushbutton Pb { .text “#1”; }
}
}
model window MWi {
groupbox Gb {
pushbutton Pb {.text “#2”; }
}
}
on dialog start
{
print Pb.text; // ergibt #1, obwohl Pb mehrdeutig.
// Nach speichern (mit –writedialog) und erneutem Simulieren => #2
exit();
}
32.2.9 Auswirkungen für IDM-Anwendungen (also für die Kunden)
Wegen den geschilderten Problemen in „Hinweise auf Problemstellen und Probleme der Vorgängerversionen“ können Dialoge zunächst nicht ladbar sein. Zuerst müssen die Mehrdeutigkeiten aufgelöst werden. Dies kann entweder von Hand geschehen oder unter Zuhilfenahme des IDM-Simulationsprogramms.
32.2.10 Startoptionen und Umgebung
Für Notfälle gibt es noch für eine gewisse Zeit die Umgebungsvariable IDM_LABEL_STRICT. Wird diese auf false gesetzt, wird die Erkennung der Mehrdeutigkeit ausgeschaltet (Zu beachten – diese wird nur einmal initial ausgewertet). Dadurch können Dialoge mit Mehrdeutigkeiten ladbar gemacht werden.
Um bei vorhandenen Mehrdeutigkeiten in den Dialogen/Modulen eine Anwendung zu einer eindeutigen Referenzierung zu migrieren kann die Option ‑slack beim Simulationsprogramm IDM verwendet werden. Dadurch wird vor dem Laden des Dialoges die Erkennung von Mehrdeutigkeiten ausgeschaltet (altes Verhalten). Nach dem Laden wird wieder entsprechend dem Wert der Umgebungsvariablen IDM_LABEL_STRICT die Erkennung ein/ausgeschaltet.
Durch Kombination von ‑slack mit ‑writedialog kann ein solches Modul mit unaufgelösten Mehrdeutigkeiten in ein Modul mit eindeutiger Referenzierung überführt werden.
32.2.11 Bekannte Fehler/Probleme des IDM
Es gibt Operationen, wie z.B. das Anlegen eines benannten Objektes, Setzen des Bezeichners oder Umhängen zu einem andern Vater, für die es notwendig wird, festzustellen, ob dieser Bezeichner schon in der Hierarchieebene existiert. Diese Überprüfung berücksichtigt die Vererbung des Bezeichners nicht.
Das hat zur Folge, dass, wie in folgendem Beispiel aufgezeigt, im Fall (a) der Bezeichner MPb (#3) nicht gesetzt werden kann, da der Bezeichner durch ein geerbtes hierarchisches Kind in der Instanz Wi vorhanden ist. Im Fall (b) ist wiederum der Normalfall aufgezeigt (kein geerbter Bezeichner vorhanden), bei dem die Setzung des Bezeichners möglich ist.
dialog D
model pushbutton MPb {};
model window MWi {
MPb {} // #1
}
MWi Wi { // Wi erbt ueber MWi das Kind MPb (#2)
pushbutton MPb {} // #3 – WARNING - Bezeichner MPb an Wi schon
// vorhanden ueber das geerbt. hier. Kind .MPb
}
window Wi2 {
MPb MPb {} // #4
D.MPb {} // #5
}
on dialog start {
// (a)
print Wi.MPb; // referenziert #2.
print Wi.PUSHBUTTON; // referenziert #3.
// (b)
print Wi2.MPb; // referenziert #4
print Wi2.MPb:[1]; // referenziert #5
exit();
}
32.3 Die Layoutbox
Sehr oft hat man das Problem, dass Objekte oder Bausteine von Objekten angeordnet werden müssen.
Dies ist von Hand zwar möglich, jedoch
- umständlich und
- anfällig
falls sich irgendwelche Objekte in ihrer Größe oder Position ändern.
Hier schafft die Layoutbox Abhilfe, Sie ist ein Containerobjekt, in das die anzuordnenden Objekte/Bausteine einfach hineingeworfen werden können. Diese werden automatisch, überschneidungsfrei angeordnet.
Die Layoutbox versucht, die Objekte nacheinander anzuordnen, passt ein Objekt nicht mehr in eine Zeile / Spalte, so wird es in die Nächste platziert.
Es wird außerdem dafür gesorgt, dass alle Objekte erreichbar sind, d.h. wenn ein Objekt nicht mehr sichtbar dargestellt werden kann (z.B. weil das Vaterfenster zu klein ist), werden Scrollbars eingefügt.Die virtuellen Größen der Layoutbox werden (solange wrap true ist) immer gesetzt. Sie können nicht beeinflusst werden, können jedoch abgefragt werden um die Arbeitsfläche herauszubekommen, d.h. die virtuellen Größen können kleiner oder größer sein als die wirklichen Größen.
Eine Spaltenbreite oder Zeilenhöhe wird immer nach dem größten Objekt der jeweiligen Spalte/Zeile bestimmt. Alle anderen Objekte richten sich dann entsprechend aus.
Falls zeilenweise ausgerichtet wird, wird yauto auf die Zeilenhöhe bezogen. xauto hat keine Bedeutung, da die Objekte grundsätzlich im gleichen Abstand nacheinander angeordnet werden.
32.3.1 Objektdefinition
Definition
{export} layoutbox {<Identifikator>}
{
<Attributklassen>
}
Ereignisse |
extevent dbselect help hscroll key paste scroll select vscroll |
Kinder |
Canvas Checkbox Combobox Control Editierbarer Text Groupbox Bild Layoutbox Listbox Menübox Notebook Pushbutton Radiobutton Record Rectangle Scrollbar Spinbox Splitbox Statictext Tablefield Treeview |
Vater |
Dialog Fenster Groupbox Layoutbox Module Splitbox Toolbar Notepage Control |
Menü |
Popup |
32.3.2 Attribute
32.3.2.1 Neue Attribute
Attribut |
Datentyp |
Wertebereich |
Eigenschaften |
Kurzbeschreibung |
---|---|---|---|---|
direction |
integer |
1 .. 2 |
SGCI |
Die Ausrichtung der auszurichtenden Objekte kann mit .direction = 2 zeilenweise oder mit .direction = 1 spaltenweise gewählt werden. Der Defaultwert ist 2. |
wrap |
boolean |
true/false |
SGCI |
Bestimmt, ob eine Neuberechnung der Kinder stattfinden muss, wenn die Layoutbox die Größe ändert (z.B. durch ein Resize). |
mincolwidth |
integer |
0..65536 |
SGCI |
Gilt für spaltenweise ausgerichtet: Gibt die Mindestbreite für ein Objekt mit .xauto = 0 an, falls sich kein anderes Objekt oder nur noch weitere Objekte mit .xauto = 0 in der jeweiligen Spalte befinden. Dieses Attribut wird für zeilenweise ausgerichtet ignoriert. |
minrowheight |
integer |
0..65536 |
SGCI |
Gilt für zeilenweise ausgerichtet: Gibt die Mindesthöhe für ein Objekt mit .yauto = 0 an, falls sich kein anderes Objekt oder nur noch weitere Objekte mit .yauto = 0 in der jeweiligen Zeile befinden. Dieses Attribut wird für spaltenweise ausgerichtet ignoriert. |
xmargin |
integer |
0..65536 |
SGCI |
Gibt den rechten und linken Rand innerhalb der Layoutbox an. |
ymargin |
integer |
0..65536 |
SGCI |
Gibt den oberen und unteren Rand innerhalb der Layoutbox an. |
xspacing |
integer |
0..65536 |
SGCI |
Gibt den horizontalen Abstand der Kindobjekte untereinander an. |
yspacing |
integer |
0..65536 |
SGCI |
Gibt den vertikalen Abstand der Kindobjekte untereinander an. |
32.3.3 Detailbeschreibung Attribute
32.3.3.1 Neue Attribute
32.3.3.1.1 direction
Regelsprache |
C |
COBOL |
Eigenschaften |
|
---|---|---|---|---|
Identifikator |
direction |
AT_direction |
AT-direction |
SGCI |
Datentyp |
integer |
DT_integer |
DT-integer |
|
Wertebereich: |
1..2 |
Defaultwert: |
2 (Zeilenweise) |
Klassifizierung: |
Objektspezifisches Attribut |
Mit diesem Attribut kann die Ausrichtungsart festgelegt werden.
Es stehen 2 Möglichkeiten zur Auswahl:
-
Zeilenweise ausrichten
Die Kinder der Layoutbox werden in der Reihenfolge, wie sie im Kindvektor stehen, zeilenweise angeordnet. In jeder Zeile wird die Maximalhöhe bestimmt. Anhand dieser werden die Kinder der Layoutbox dann ausgerichtet. Wenn in einer Zeile kein Platz mehr ist, d.h. das Objekt nicht mehr sichtbar wäre wenn es in der selben Zeile angeordnet werden würde, wird das nächste Kind in die nächste Zeile positioniert.
-
Spaltenweise ausrichten
Die Kinder der Layoutbox werden in der Reihenfolge, wie sie im Kindvektor stehen, spaltenweise angeordnet. In jeder Spalte wird die Maximalbreite bestimmt. Anhand dieser werden die Kinder der Layoutbox dann ausgerichtet. Wenn in einer Spalte kein Platz mehr ist, d.h. das Objekt nicht mehr sichtbar wäre wenn es in der selben Spalte angeordnet werden würde, wird das nächste Kind in der nächsten Spalte positioniert.
32.3.3.1.2 wrap
Regelsprache |
C |
COBOL |
Eigenschaften |
|
---|---|---|---|---|
Identifikator |
wrap |
AT_wrap |
AT-wrap |
SGCI |
Datentyp |
boolean |
DT_boolean |
DT-boolean |
|
Wertebereich: |
true/false |
Defaultwert: |
true |
Klassifizierung: |
Objektspezifisches Attribut |
Mit diesem Attribut kann der Umbruch ein- und ausgeschaltet werden.
Umbruch heißt, dass bei einer Größenänderung oder Änderung des visible-Attributs der Layoutbox die Kinder gegebenenfalls neu sortiert werden, damit die Kinder alle sichtbar, bzw. erreichbar bleiben.
Wenn der Umbruch ausgeschaltet wird, werden keine Änderungen mehr durchgeführt (z.B. Änderungen an den Attributen der Layoutbox direction, .ymargin, .xmargin... oder deren Kindern).
Falls der Umbruch von Anfang an ausgeschaltet ist, werden die Objekte von der Layoutbox nicht angeordnet.
32.3.3.1.3 xspacing
Regelsprache |
C |
COBOL |
Eigenschaften |
|
---|---|---|---|---|
Identifikator |
xspacing |
AT_xspacing |
AT-xspacing |
SGCI |
Datentyp |
integer |
DT_integer |
DT-integer |
|
Wertebereich: |
0..65536 |
Defaultwert: |
0 |
Klassifizierung: |
Objektspezifisches Attribut |
Mit diesem Attribut kann der horizontale Abstand zwischen den Kindern der Layoutbox angegeben werden.
32.3.3.1.4 yspacing
Regelsprache |
C |
COBOL |
Eigenschaften |
|
---|---|---|---|---|
Identifikator |
yspacing |
AT_yspacing |
AT-yspacing |
SGCI |
Datentyp |
integer |
DT_integer |
DT-integer |
|
Wertebereich: |
0..65536 |
Defaultwert: |
0 |
Klassifizierung: |
Objektspezifisches Attribut |
Mit diesem Attribut kann der vertikale Abstand zwischen den Kindern der Layoutbox angegeben werden.
32.3.3.1.5 xmargin
Regelsprache |
C |
COBOL |
Eigenschaften |
|
---|---|---|---|---|
Identifikator |
xmargin |
AT_xmargin |
AT-xmargin |
G |
Datentyp |
Integer |
DT_integer |
DT-integer |
|
Wertebereich: |
0..65536 |
Defaultwert: |
0 |
Klassifizierung: |
Objektspezifisches Attribut |
Mit diesem Attribut kann der rechte und linke Abstand zwischen der Layoutbox und den Kindern angegeben werden.
32.3.3.1.6 ymargin
Regelsprache |
C |
COBOL |
Eigenschaften |
|
---|---|---|---|---|
Identifikator |
ymargin |
AT_ymargin |
AT-ymargin |
SGCI |
Datentyp |
integer |
DT_integer |
DT-integer |
|
Wertebereich: |
0..65536 |
Defaultwert: |
0 |
Klassifizierung: |
Objektspezifisches Attribut |
Mit diesem Attribut kann der obere und untere Abstand zwischen der Layoutbox und den Kindern angegeben werden.
32.3.4 Hinweise
Es ändern sich für die Kinder der Layoutbox die Bedeutung einiger Attribute:
Attribut |
Datentyp |
Wertebereich |
Eigenschaften |
Kurzbeschreibung |
---|---|---|---|---|
.xauto |
short |
-1 .. 1 |
|
Bei spaltenweise angeordnet: das Objekt wird in der jeweiligen Spalte angeordnet, deren Breite sich nach dem breitesten Objekt richtet. Für -1 vom linken Rand der Spalte, für 1 vom rechten Rand der Spalte, für 0 wird es auf die Spaltenbreite aufgezogen. Falls nur Objekte mit .xauto = 0 in einer Spalte sein sollten, bekommen sie den Wert .mincolwidth zugewiesen. Für zeilenweise hat dieses Attribut keine Bedeutung. |
.yauto |
short |
-1 .. 1 |
|
Bei zeilenweise angeordnet: das Objekt wird in der jeweiligen Zeile angeordnet, deren Höhe sich nach dem größten Objekt richtet. Für -1 vom unteren Rand der Zeile, für 1 vom oberen Rand der Zeile, für 0 wird es auf die Zeilenhöhe aufgezogen. Falls nur Objekte mit .yauto = 0 in einer Zeile sein sollten, bekommen sie den Wert .minrowheight zugewiesen. Für spaltenweise hat dieses Attribut keine Bedeutung. |
32.3.4.1 Posrastering
Das Posrastering von Kindern der Layoutbox wird zwar unterstützt, macht aber wenig Sinn.
Es wird nur aus Gründen des Editierens eines Dialoges unterstützt.
Wenn man mit dem Editor ausprobieren möchte, ob sich die Layoutbox besser als Container eignet als die Groupbox, würde das Posraster-Attribut sonst an allen Kindern gelöscht werden. Wenn dem Anwender die Groupbox dann doch besser erscheinen würde, müsste dieser die Attribute von Hand an allen Kindern wieder neu setzen.
Wenn Posrastering für die Kinder der Layoutbox eingesetzt wird, kann das Ergebnis schlechter als erwartet aussehen, da das Auf- bzw. Abrunden von beim Positionieren von verschiedenen angegeben Objekten (mit und ohne Border) zur ungleichmäßigen Ausrichtung von Objekten führt.
32.3.4.2 Virtuelle Größen
Die Layoutbox berechnet die virtuelle Breite und Höhe selber. Sie kann zwar vom Benutzer gesetzt und ausgelesen werden, Setzungen vom Benutzer werden jedoch ignoriert.
Die virtuellen Größen geben immer den Arbeitsbereich an, d.h. die Rechteckfläche, die die Kinder der Layoutbox mit ihren Rändern (Margin) umfassen.
32.3.5 Beispiel
Eine simple Verwendung des Layoutbox-Objektes kann wie folgt aussehen:
dialog Dialog { }
color Black “black”
window W
{
.title "Layoutbox-Demo";
.width 400;
.height 400;
child layoutbox Lb {
.xauto 0;
.yauto 0;
.xleft 5;
.xright 5;
.ytop 5;
.ybottom 50;
.xspacing 10;
.yspacing 10;
.xmargin 20;
.ymargin 20;
.wrap true;
child pushbutton Pb1 {
.text "Pushbutton1";
}
child statictext St1 {
.text "Statictext";
}
child groupbox Gb1{
.bgc Black;
.xauto 1;
.yauto 1;
.width 100;
.height 100;
}
}
on close {exit();}
}
32.4 Neues Objekt Combobox für Motif
Für die Plattform Motif 2.1 unterstützt der Poptext jetzt auch das .style-Attribut mit allen Werten (poptext, edittext und listbox) und das Attribut .showitem.
Weitere Einzelheiten zum Poptext sind dem Kapitel „poptext (Combobox)“ in der „Objektreferenz“ zu entnehmen. Die Anmerkungen für Motif in diesem Kapitel gelten jetzt nur noch für Motif 1.2.
Die Implementation basiert auf einem neuen Oberflächenobjekt (Widget), das ab Motif 2 verfügbar ist. Aus diesem Grund ergaben sich allerdings geringfügige Änderungen, die sich
auch auf .style = poptext auswirken, wie zum Beispiel:
- Geändertes Aussehen des Pfeiles zum Aufklappen der Liste.
- Geänderte Selektionsfarbe.
- Geänderte Größe des Poptextes, er ist jetzt etwas höher und etwas schmaler. Dies kann zur Folge haben, dass eventuell Buchstaben unten abgeschnitten werden (z.B.
gÖ@
), wenn eine Höhe vorgegeben wurde. Hat man keine Höhe vorgegeben, so wird der Poptext entsprechend größer dargestellt. - select-Ereignis tritt jetzt schon auf, wenn ein anderer Text ausgewählt bzw. in das Textfeld übernommen wird. Bisher gab es dieses Ereignis, wenn die Auswahlliste geschlossen wurde. Jetzt gibt es das select-Ereignis nur noch, wenn sich tatsächlich ein Eintrag (das Attribut .activeitem) geändert hat.
Der Poptext unter Motif 2.1 lässt sich jetzt zusätzlich per Tastatur mittels Strg + Cursor Abwärts oder Strg + Cursor Aufwärts auf- bzw. zuklappen.
32.5 Toggelbares Image für Motif und Microsoft Windows NT
Das Image Objekt ist jetzt um ein zusätzliches ".style" Attribut erweitert und kann zwei Zustände (aktiv/inaktiv) bekommen. Das .style Attribut kann auch zwei Werte erhalten:
- .style : Pushbutton-Style
- .style : Checkbox-Style
Zwischen den Zuständen (aktiv/inaktiv) wird bei der ".style" Einstellung 'Checkbox' umgeschaltet. Jedem Zustand kann ein Bild zugeordnet werden. Dazu ist auch das Image-Attribut ".picture" indiziert worden:
- picture[tile_default] <Tile> - Bild im inaktiven Zustand
- picture[tile_active] <Tile> - Bild im aktiven Zustand
Bei der Einstellung Pushbutton ist das Umschalten zwischen den Zuständen nicht möglich, das Objekt bekommt das für picture[0] zugewiesene Bild. Das Verhalten in diesem Fall entspricht dem Verhalten früherer Versionen.
Das Image Objekt unterstützt jetzt auch GIF-Bilder (89A Format), die transparente Farben enthalten.
32.6 Microsoft Windows NT
- Leere Messagebox: Es kam vor, dass leere Fehler-Messageboxen angezeigt wurden. Dies war immer dann der Fall, wenn die Fehlermeldungen eine bestimmte Länge überschritten hatten.
- Gnats 8724: Icons werden wieder in der gewünschten Größe dargestellt. Wird ein Icon z.B. 16x16 aus einer Iconresource mit verschieden möglichen Auflösungen verlangt, z.B. 16x16 und 32x32, so wird zuerst die am besten passende Größe herausgesucht, evtl. skaliert und dargestellt.
-
Gnats 8394: Die Unterstützung für Wheelmäuse wurde für folgende Objekte hinzugefügt:
- Tablefield: Durch Benutzung des Rädchens wird vertikal nach oben und unten gescrollt. In Kombination mit der Shift-Taste wird seitenweise und mit Strg horizontal gescrollt.
- Poptext: Im aufgeklappten Zustand wird vertikal gescrollt, der aktive Eintrag bleibt unverändert. Im zusammengeklappten Zustand öffnet sich der Poptext.
- Groupbox: Es wird zeilenweise nach oben / unten gescrollt. Auch hier ist in Kombination mit Shift seitenweises Scrollen und mit Strg horizontales Scrollen möglich. Die Zeilenhöhe kann weiterhin mit dem Attribut .vsb_linemotion eingestellt werden.
- Treeview: Es wird zeilenweise nach oben / unten gescrollt. Bei Shift seitenweises Scrollen; bei Strg horizontales Scrollen.
- Edittext multiline: Es wird zeilenweise nach oben / unten gescrollt.
- Listbox: Es wird zeilenweise nach oben / unten gescrollt. Bei Shift seitenweises Scrollen; bei Strg horizontales Scrollen.
Bei Logitech-Treibern muss bei den Mauseigenschaften Nur MS Office kompatiblen Bildlauf verwenden eingestellt werden, da sich der Treiber sonst nicht an den Windows-Standard hält.
32.7 JAVA-Window-Interface
- Es ist jetzt möglich, die Kommunikation zwischen Server und Client mit SSL zu verschlüsseln. Man muss dazu eine IDM-Anwendung bauen und die Lizenz der Verschlüsselungssoftware besitzen
- Den IDM- Objekten können jetzt Java- Cursors zugewiesen werden.
-
Tablefields können nun editiert werden, d.h. folgende Attribute werden nun unterstützt: .edittext, .editable, .edittype, .editpos, .format[][], .maxchars[][]. Dadurch werden jetzt auch folgende Events unterstützt: EV_charinput EV_modified.
Einschränkungen
- Rowheader können nicht editiert werden.
- Multiline Inhalte werden nicht unterstützt d.h. .editpos=true, .sizraster=true und .rowheight>1 => zum Editieren wird trotzdem ein singleline Edittext genommen.
32.8 DM-Kern
- Gnats 8673: Exportierte Funktionen von nicht exportierten Applikationen gelangten nicht in den Interface-Teil eines Binärmoduls. Deshalb konnte beim Lesen der Binärmodule (ohne Interface-Datei) die Funktion nicht als exportiert angelegt werden.
- Gnats 8769: Setvals auf dynamisierte Ressourcen (Font, Tile, Cursor, Color) zeigen Wirkung.
- Gnats 8765: Initialwerte beim Parsen korrigiert.
- Gnats 8741: Export-Imports bekommen keine Label-Referenz auf die Hülle zugewiesen, um die Eindeutigkeit zu gewährleisten.
32.9 Debugger
Der Debugger unter Motif besitzt nun die gleiche Oberfläche wie der unter MS-Windows.
Einschränkungen
- Motif allgemein: keine Statusbar
-
Motif 1.2: keine Combobox deswegen:
- Statt Poptext wird ein Edittext verwendet.
- Die Kurzliste der letzten eingetragenen Expressions ist über das Menü zu erreichen.
- Keine Kurzliste der letzten Eingaben bei der Suche von Regeln.
32.10 Motif
- Gnats 6776: Wird ein Fenster mit einer Groupbox durch eine select-Regel geschlossen (die on select-Regel hängt an der Groupbox), so löst ein Image, welches genau unter der Groupbox in einem anderen Fenster liegt, kein select-Ereignis mehr aus.
- Gnats 3940: Setzt man zur Laufzeit an einem Image einen Text, wird das Image vergrößert und der Text unter dem Image dargestellt. Löscht man nun den Text des Images (Image.text = null), wird das Image auf die ursprüngliche Größe zurückgesetzt.
- Gnats 8538: Bei Treview-Objekt sind folgende Fehler beseitigt: Es ist jetzt möglich .sensitive auf true zu setzen auch wenn beim Erzeugen des Treeview .sensitive false war oder nach dem Umschalten des Attributs .visible auf false und dann wieder auf true gesetzt wurde.Beim Rauf- und Runterselektieren mit den Pfeiltasten wird jetzt auch das Kern-Attribut .activeitem aktualisiert und ein activate-Ereignis gesendet. Nach dem Setzen des .activeitem-Attributs aus der Regelsprache wird auch der Fokusrahmen mit aktualisiert. Das .topitem-Attribut bleibt nach dem Umschalten sichtbar → nicht sichtbar → sichtbar richtig dargestellt.
- Gnats 8646: Wird an einem Image-Objekt das Attribut .picture nicht gesetzt, so hat es nach seiner Erzeugung falsche Größe (unabhängig von .sizeraster).