Lade...
 

SetFormat (Obox-Widget)

SetFormat (Obox-Widget)

SetFormat(windowID, oboxID), SetFormat(, oboxID), SetFormat

Parameter: Bezeichner eines Windows und einer Objektbox

Stack
Stack Position Beschreibung
Stack(In) Top ]
  Top-1 Parameter n
  . . . . . .
  Top-n Parameter 1
  Top-n-1 [
Stack(Out)   -

Für den gleichlautenden Befehl für FString-Widgets siehe: SetFormat (FString).

Welche Daten eine Objektbox auf welche Weise darstellt, wird durch Formatelemente gesteuert. SetFormat baut aus den Parametern vom Stack ein Formatelement für die als Operand angegebene Objektbox auf. Folgende Parameter können übergeben werden:

1 "KLASSE::ausdruck"
bzw.
Path(Klasse::ausdruck)
Klasse und Zugriffsausdruck als Zeichenkette obligatorisch. (Regeln für call(Proc) in Zugriffsausdrücken sind hier beschrieben)
2 Non-primitive Statement   optional
3 x Spaltenposition (in Minicells) Default x = 0
4 y Zeilenposition (in Minicells) Default y = 0
5

FIX_WIDTH(width)
WIDTH(width)
196388

gesetzte Breite für erste Anzeige (width in Minicells) Default width = -1 (deaktiviert)
s.a. "... %s ..."
6 JUSTIFY_RIGHT x definiert rechte Randposition  
7 COLOR col Farbe Default col = BLACK
8 FONT f Font Default f = -1. Ist die Font mit dem Widget nicht kompatibel, wird sie verändert.
9 flag Flags für ViewExport Default flg = 0
10 "... %s ..." Formatstring für sprintf optional; z.B. "%.-25s" um die ausgegebene Zeichenkette auf 25 Stellen zu begrenzen
s.a. FIX_WIDTH(width)
11 COLUMN k k-te Spalte optional
12 NO_PRINT Spalte bei der Übernahme mit PutLine ausschließen optional
13 NO_DRAIN Spalte bei OboxEdit nicht editierbar (Daten nur anzeigen) optional
14 COMBO für Stringfeld bei OboxEdit Combobox erzeugen optional, Default: String-Widget
15 TEXT für Stringfeld bei OboxEdit Text-Widget erzeugen optional, Default: String-Widget
16 BREAK Formatliste nicht weiter durchsuchen optional
17 VARYING_ENUM Spalte mit variablem Datentyp - z.B. bei CX_ATTRIBUTE::Value() optional
18 NODE Knoten: Zugriffsausdruck beschreibt Unterobjekte (kein ViewExport etc.) optional (alternativ)
19 GROUP Gruppe: Zugriffsausdruck beschreibt Sammeleigenschaft für Objekte optional (alternativ)
20 HEADER h Spaltenüberschrift optional; h ist ein String oder ein Multiple String, der auch in Form einer Variablen innerhalb der SetFormat Anweisung angegeben werden kann
Folgende Formatanweisungen sind MorphIT-Spezifisch und werden nativ aktuell nicht unterstützt.
21 URL(Ausdruck) Zellenlink optional. Der angegebene Ausdruck muss ein gültiger Zugriffspfad sein.
22 TOOLTIP(Ausdruck) Zellentooltip optional. Der angegebene Ausdruck muss ein gültiger Zugriffspfad sein.
23 THUMBNAIL(Breite,Höhe) Vorschaubild optional
24 LINK(Id, Ausdruck) Zellen-Linkwidget Die Zellen-Widget-Id und ein optionaler Zugriffsausdruck, über den der Text/ das Bild des Links festgelegt werden kann.
25 BUTTON(Id, Ausdruck) Zellen-Buttonwidget Die Zellen-Widget-Id und ein optionaler Zugriffsausdruck, über den der Text/das Bild des Buttons festgelegt werden kann.

Der erste in der Tabelle aufgeführte Parameter ist notwendig. Wenn FillObox ein Objekt darstellen will, werden alle Formatelemente für die Klasse bzw. eine Basisklasse des Objekts ausgewertet. Es ist möglich, in einer Objektbox Objekte verschiedener Klassen zugleich darzustellen. Andererseits wirkt die Objektbox bei einer Collection mit Objekten unterschiedlicher Klasse als Filter, da sie nur zu ihrer Formatliste passende Elemente darstellt. Der Zugriffsausdruck im ersten Parameter führt zu dem Datenfeld, das - konvertiert in einen String - an Position x, y in einer Zeile der Listbox dargestellt werden soll.
Standardannahme für y ist Null. Für eine Objektbox mit Flag AUTO_POSITION kann auch der x-Wert entfallen, da er automatisch berechnet wird. (Im ObjectTree wird die Position/AutoPosition ignoriert, da sich die Position aus der Struktur ergibt.)

Das AUTO_POSITIONing in der ObjectListView kann interaktiv vom Anwender für jede Spalte dadurch deaktiviert werden, in dem er per Maus-Drag in der Spaltenüberschrift rechts von der Spalte die Spaltenbreite ändert. Eine so geänderte Spaltenbreite bleibt auch beim nächsten AUTO_POSITIONing (z.B. beim Scrollen) bestehen. Erst wenn rechts von der Spalte in der Spaltenüberschrift doppelt geklickt wird, wird das AUTO_POSITIONing für die Spalte wieder eingeschaltet.
Wenn AUTO_POSITION als Flag für die ObjectListView gesetzt ist, ist standardmäßig AUTO_POSITIONing für jede Spalte dieser ObjektListView aktiviert. Dieses Standardverhalten kann mit dem Parameter FIX_WIDTH überschrieben werden. Mit FIX_WIDTH(width), width größer oder gleich 0, wird die Liste genau so angezeigt, als hätte bereits der User sie per Maus-Drag in der Spaltenüberschrift auf die Breite width (in Minicells) gesetzt.
Die gesetzte Breite ist also genauso durch Doppelklick (AUTO_POSITION wieder einschalten) oder erneuten Maus-Drag in der Spaltenüberschrift veränderbar, als hätte der Anwender die Einstellung interaktiv vorgenommen.

Da mehrere SetFormat-Anweisungen für eine Spalte wirksam sein können, ist es möglich, dass für eine Spalte mehrere FIX_WIDTH-Breiten angegeben sind. In einem solchen Fall wird immer der größte angegebene Wert verwendet.

FLAG

Mit Parameter 9 können Flags an die Konvertierungsfunktion eines Objektes (ViewExport) übergeben werden.
Die Schreibweise FLAG flag ist obsolet (d.h. Voranstellen des Markers FLAG), wird aber aus Gründen der Kompatibilität zu älteren Versionen des ClassiX-Systems akzeptiert.

Ist der 10. Parameter angegeben, so wird der String als Input für sprintf weiter modifiziert. Dafür muss der Formatstring genau einen Platzhalter("%s") für den Orginalstring enthalten.
Beabsichtigt man nur die Länge der Anzeige zu beschränken, ist eine Angabe mit FIX_WIDTH einer Formatierung der Form "%.30s" oder "%-.30s" vorzuziehen. Dadurch erhält der Anwender die Gelegenheit bei Wunsch sich den gesamten Text anzusehen. Außerdem wird ein ständiges AUTO_POSITIONing für die entsprechende Spalte verhindert.

COLUMN
Im Normalfall wird jede Spalte durch eine einzige SetFormat-Anweisung beschrieben. Jedes SetFormat ohne COLUMN schaltet dazu einen internen Zähler um 1 weiter. Soll nun eine Spalte mehrere Format haben, ist so vorzugehen:

[ Path(CX_X::aaa) ] SetFormat // Spalte 0 [ Path(CX_X::bbb) ] SetFormat // Spalte 1 [ Path(CX_Z::bbb) COLUMN 1 ] SetFormat // Spalte 1 [ Path(CX_X::ccc) ] SetFormat // Spalte 2

Nur die mehrfach definierten Spalten müssen eine COLUMN-Anweisung tragen. COLUMN verhindert, dass der interne Zähler weitergeschaltet wird, so dass im Beispiel die vierte SetFormat-Anweisung die dritte Spalte beschreibt, auch ohne COLUMN.
Gründe für mehrfach definierte Spalten sind Bitmaps und die Darstellung von verschiedenen Klassen.

Wenn mehrere Formatangaben für eine Spalte definiert sind darf nur eine davon angewendet werden. Die auszuwählende ergibt sich wie folgt:

  1. Über den Klassennamen wird eine Vorselektion vorgenommen: Eine Formatanweisung ist nur für die angegebene Klasse definiert und macht für andere Klassen nichts. Als Beispiel s.o.
  2. Über den Zugriffspfad wird INVALID zurückgegeben: Bei der Auswertung liefert ein Teil oder der gesamte Ausdruck INVALID zurück. Dadurch wird die Auswertung abgebrochen und die Formatanweisung ignoriert. Beispiel:
Define(LocalIsNotPointer) Dup Copy(Type()) "POINTER" = if { Drop INVALID } ; Define(LocalIsPointer) Dup Copy(Type()) "POINTER" = ifnot { Drop INVALID } ; [ "CX_SLOT_ATTRIBUTE::call(LocalIsNotPointer).Value()" HEADER T("Wert", "Value") COLUMN 3 ] SetFormat [ NO_DRAIN "CX_SLOT_ATTRIBUTE::call(LocalIsPointer).call(G_GetAttributePointerValue)" HEADER T("Wert", "Value") COLUMN 3 ] SetFormat

Über die Makroaufrufe (call) in den Zugriffsausdrücken der Formatanweisungen wird abhängig vom darzustellenden Objekt exakt eine der beiden Zeilen ausgewählt. LocalIsPointer und LocalIsNotPointer liefern im Gegensätzlichen Fall jeweils entweder das Objekt oder INVALID zurück. Der Headerwert ist für beide Darstellungen derselbe, so dass hier keine Konflikte auftreten.

PUSH / call

ACHTUNG: Push() ist veraltet. Bitte nicht mehr benutzen. Benutzen Sie stattdessen ein "call(Makroname)" im Zugriffsausdruck:

[ Path(CX_STRUCTURE::call(ExpandStructureNames)) ] SetFormat

Wenn FillObox für ein Objekt o dieses Formatelement auswertet, wird das angegebene Statement mit folgender Stackbelegung ausgeführt:

Stack
Stack   Beschreibung
Stack(In)   Objekt o
Stack(Out)   ein String oder eine Bitmap

Ein einfaches Beispiel zeigt diese Möglichkeit.
Liefert die Ausführung des Statements eine Bitmap zurück, wird diese entsprechend eingefügt: Ohne Angabe des Flags BITMAP_SIZE als Parameter der ObjectBox in ihrer Originalgröße, ansonsten wird sie so gestretched, dass sie die gesamte Breite der jeweiligen Spalte ausfüllt.
Genauso wie (über Angabe des Parameters COLUMN) Bitmap- und String-Spalten gemischt werden können, kann auch dasselbe Statement für einige Objekte Bitmaps und für andere Strings zurückgeben.

Ein Ausdruck mit call() kann auch ein Objekt zurückgeben und dann können verschiedene Pozeduraufrufe im Zugriffspfad verkettet werden. Bsp:

[ Path(CX_PERSON::call(FindNiece).call(FindUncle)) ] SetFormat

Sollte eine Prozedur in dieser Kette INVALID zurückgeben, dann werden die nachfolgenden Prozeduren nicht mehr ausgewertet. Falls die letzte Prozedur ein Objekt zurückgibt und keinen String, dann wird implizit String ausgeführt.

Bei der "modernen" Variante der ObjectBox, ObjectListView, ist es unbedingt erforderlich, dass das Ergebnis einer solchen Formatanweisung ausschließlich vom Objekt selber, und nicht etwa vom Zustand des Systems (globale Variablen / Modulvariablen), abhängt. Der Grund hierfür ist, dass der Zeitpunkt, zu dem die visuelle Repräsentanz der Elemente angelegt wird, und damit die Reihenfolge, in der die Formatanweisungen ausgeführt werden, von vornherein nicht bekannt ist; und nicht etwa der Reihenfolge des Einfüllens der Objekte in die ObjectListView gleichen muss.

Wenn eine ObjectListView für einen Ausdruck vorgesehen ist und es vorkommt, dass in einer Zelle sowohl Text als auch ein Bitmap enthalten ist, kann nur vernünftig nach der Nummer sortiert werden, wenn als erstes die Spaltendefinition mit der Nummer und anschließend die des Bildes definiert wird:

// At first the definition of the column with the number (to enable right sorting!) [ Path(CX_LINK_TXN::UniqueID()) HEADER T("Auftrag", "Order") FIX_WIDTH(100) ] SetFormat // Then the definition of the column with the picture! [ Path(CX_LINK_TXN::call(Local_G_GetPicture)) COLUMN 0 ] SetFormat ...


Soll der Text in dieser Konstellation rechtsbündig gedruckt werden, so muss die Angabe JUSTIFY_RIGHT sowohl bei der Bitmap als auch bei der Text-Formatangabe gemacht werden.

Wird eine Formatangabe mit Flag BREAK für eine Klasse als zutreffend ausgewählt, so wird die Formatliste nicht weiter durchsucht. Flag BREAK löst dabei folgendes Problem: Enthält eine Formatliste Formate sowohl für eine Klasse A als auch eine davon abgeleitete Klasse B, so werden für ein Objekt der Klasse B normalerweise beide Formatangaben benutzt. Dies ist falsch, wenn das Format für B eine Spezialisierung einer allgemeineren Angabe für A ist; d.h. für Objekte A soll Format A։։expression benutzt werden, während für Objekte B ausschließlich die Angabe B։։expression gültig ist. Um das zu erreichen muss die speziellere Angabe (B։։expression) mit Flag BREAK und vor A։։expression angegeben werden.

NODE Lists,Tree und GROUPs:
Über die Angabe NODE wird dem Format eine andere Bedeutung zugewiesen. Anstatt für die Darstellung eines Ausdrucks zuständig zu sein, geben NODE-SetFormats die Datenelemente an, über die strukturierte Daten verknüpft sind.
Die Klasse im Parameter 1 gibt filtert dabei die Objekte, für die Unterstrukturen ausgewertet werden sollen. Der Zugriffsausdruck des 1. Parameters gibt die Daten-Quelle dieser Unterstrukturen an, also z.B. eine Collection oder einen Pointer. Von allen anderen Parametern werden nur BREAK und COLUMN unterstützt, wobei COLUMN für das jeweilige Format keine Auswirkung hat (NODE impliziert immer COLUMN 0). Es ist ratsam, NODE-Formate immer als letzte SetFormat-Anweisungen zu definieren. Bei NODE kann der Zugriffspfad mehrmals ausgewertet werden (s. ObjectTree)!
Auch über das GROUP-Flag werden Daten strukturiert. GROUPs unterscheiden sich von NODEs dahingehend, dass sie keine Zugriffe auf Objektansammlungen (wie Collections) definieren, sondern den Zugriff auf normale Datenfelder, zum Beispiel einer Enumeration. Während NODE den Zugriffsausdruck auswertet und in durch diesen adressierte Objekte verzweigt, sammelt GROUP alle (via Klassenangabe) angesprochenen Objekte und fügt für diese virtuelle übergeordnete Elemente, die Gruppen, ein. Dabei werden alle Objekte zu jeweils einer Gruppe zusammengefasst, die sich im über den Zugriffsausdruck angesprochenen Datenfeld gleichen. Während NODE also immer eine untergeordnete Stufe einfügt (in die auch verzweigt wird) fügt GROUP eine (weitere) übergeordnete Stufe ein.
Es können auch mehrere GROUPs für ein Objekt zutreffend sein. In diesem Fall werden baumartig gleich mehrere Stufen (Groups) eingefügt.
Alle weiteren Angaben in den SetFormat-Parametern werden zur Darstellung des (der) neu eingefügten Elements(/-e) verwendet. Im ObjectTree erhalten diese Gruppen-Elemente eine Bitmap, wenn weitere SetFormats angegeben werden, die Bitmaps über ein Non-primitive Statement zurückgeben. Dabei wird das erste (0.) Bitmap-Format für das Objekt selber, jeder weitere (i-te) Bitmap für die nächste (i-te) Gruppe verwendet. Überzählige Bitmaps werden ignoriert. Bekommt eine Gruppe keine Bitmap wird, wie bei der Darstellung von Elementen ohne Bitmapangaben ein Default Icon (DefIcon.bmp (822 Byte)) verwendet.
Gibt man einem Format mit der Angabe sexEnum zu der Klasse CX_PERSON zum Beispiel den zusätzlichen Parameter GROUP, werden in der Darstellung die Personen (unterhalb eines bestimmten NODEs) die Personen nach Geschlecht in eine Gruppe "weiblich" bzw. "männlich" sortiert.

Eine Besonderheit ist noch bei der Verwendung von NODE-SetFormats in ObjectLists zu beachten:
Da die ListBox, anders als die TreeView-Box von Hause aus (sprich durch die Plattform), nicht über grafische Darstellungsmittel für die Hierarchie-Visualisierung verfügt, sind bei dieser in InstantView zusätzliche Angaben erforderlich. So erfordert die Zeichnung der Stufigkeit in der Elementanordnung und die für das interaktive Expandieren und Kollabieren wichtigen + und - Button, die Angaben dreier Bitmaps in der 0. Spalte in der folgenden exemplarischen Form:

Define(GetLeafBitmap)
  leafBmp //= "tree_node.png"
;
Define(GetCollapseBitmap)
   collBmp //= "tree_collapsed.png"
;
Define(GetExpandBitmap)
    expBmp //= "tree_expanded.png"
;
.....
[ Path(CX_CLASS::call(GetLeafBitmap))     COLUMN 0 ] SetFormat
[ Path(CX_CLASS::call(GetCollapseBitmap)) COLUMN 0 ] SetFormat
[ Path(CX_CLASS::call(GetExpandBitmap))   COLUMN 0 ] SetFormat

Wichtig ist hierbei die Angabe der Spalte (COLUMN), da nur in der 0. Spalte nach den erforderlichen Bitmaps gesucht wird. Man kann die Liste auch ohne Bitmaps strukturieren, ein grafisches Expandieren und Kollabieren ist dann jedoch nicht mehr möglich. Die Reihenfolge der Angabe ist wichtig, da hierüber der jeweils zugeordnete Status bestimmt wird. Um verwirrende Darstellungen zu vermeiden, sollten alle Bitmaps gleich groß sein und die ObjectBox mit dem Flag BITMAP_SIZE versehen werden.
Eine ObjectList mit NODEs kann nicht nachträglich sortiert werden. Auch können Veränderungen nicht gespeichert werden. Um erfolglose Änderungsversuche der Users zu vermeiden, sollte ein ObjectList mit NODEs das Attribut VIEW_ONLY tragen.
Der Vorteil der Verwendung einer ObjectList gegenüber dem ObjectTree zur Darstellung strukturierter Daten, liegt darin, dass die (Format-)Strings zu einem Objekt nicht einfach mit Leerzeichen hintereinander gehängt werden, sondern die Spalten der ObjectList erhalten bleiben. Die gesamte Ausgabe bleibt also tabelliert. Die zur Visualisierung der Struktur vorgenommene Einrückung untergeordneter Objekte erfolgt in der ObjectList nur in der 0. Spalte. In dieser wird vor dem String zur Einrückung eine Punktlinie dargestellt, die den Text mit denen (nach obigen Beispiel) angegebenen Bitmaps verbindet. Es entsteht insgesamt dabei ein optischer Eindruck, der in der 0. Spalte dem des ObjectTrees ähnelt.

HEADER
Wenn in SetFormat jede Spalte über diesen Parameter benannt wird, kann die Header-Anweisung entfallen. Wenn für eine Spalte mehrere HEADER definiert wurden (das gilt auch für mehrzeilige ListViews), gewinnt immer die erste SetFormat-Anweisung mit HEADER für diese Spalte.
Existieren mehrere HEADER für eine Spalte, liegt hier ein logischer Fehler vor, der behoben werden sollte!

Beispielformat für das Format eines ObjectTrees aus dem Tutorial:

ObjectTree(tree, 5, 15, 380, 170) [ INITIALIZE: [ Path(CX_PERSON::call(Symbol)) ] SetFormat // Sets a picture if male or female [ Path(CX_PERSON::name) ] SetFormat [ Path(CX_PERSON::firstName) ] SetFormat // The children will be displayed in a node under the partens [ Path(CX_PERSON::children) NODE ] SetFormat ]

URL(Ausdruck)

Der übergebene Ausdruck wird mit dem Objekt der aktuellen Zeile ausgewertet und sollte eine absolute (mit http://, https://) oder relative URL als STRING oder ML_STRING zurückgeben oder INVALID, falls für das Objekt kein Link angezeigt werden soll. Der in der Zelle angezeigte Text wird hierdurch als Link zu der angegebenen URL dargestellt. Beim Auslösen des Links wird kein SELECT auf der ListView ausgelöst.

TOOLTIP(Ausdruck)

Der übergebene Ausdruck wird mit dem Objekt der aktuellen Zeile ausgewertet und sollte einen Tooltip als STRING oder ML_STRING zurückgeben. Um für bestimmte Objekte keinen Tooltip anzuzeigen, kann ein Leerstring zurückgegeben werden. Der Tooltip wird an der Zelle beim Hovern als Tooltip angezeigt.

THUMBNAIL(Breite,Höhe)

Falls der Zugriffsausdruck ein Bild liefert, dann kann über diese Formatanweisung die Größe (in Pixeln) festgelegt werden, in welcher das Bild in der Liste angezeigt wird. Erst beim Klicken auf das Bild zeigt sich das Bild in seiner vollen Größe

BUTTON(Id, Ausdruck) & LINK(Id, Ausdruck) - Zellen-Widgets (Nur TreeList & ObjectListView)

Für MorphIT lassen sich Zellen-Widgets angeben, die sich in einer ListView/TreeList-Zelle darstellen und in eingeschränktem Umfang Interaktion erlauben. Der optionale Zugriffsausdruck definiert den Zugriffsausdruck, der verwendet wird, um den Text des Zellenwidgets darzustellen. Falls kein Zugriffsausdruck angegeben ist, dann wird hierzu der primäre Zugriffsausdruck der Zelle verwendet.

Die Messages der Zellen-Widgets werden in der Action-Liste der dazugehörigen Liste definiert. Hierfür gibt es eine besondere Syntax, um anzugeben, auf welches Zellen-Widget sich das Event bezieht.

Die Syntax hierfür lautet: MESSAGE@ID (Aktuell wird nur SELECT unterstützt). Wird ein solches Event ausgelöst, dann ist die Zeile des Zellen-Widgets die einzige selektierte Zeile und das dazugehörige Objekt kann mittels GetObject geholt werden.

Code-Beispiel:

[ INITIALIZE: [ Path(CX_CONTAINER::str) TOOLTIP(strB) BUTTON(ID_BTN) ] SetFormat SELECT@ID_BTN: "Cell button selected on Object " GetObject String + Attention(, INFO) SELECT: "List entry selected" Attention(, INFO) ]
Einschränkung: Pro SetFormat-Anweisung ist nur ein Zellen-Widget erlaubt und Zellen-Widgets lassen sich nicht mit URL kombinieren.