Beim Entwurf eines Scripts schafft es etwas unterschiedliche Situationen, ob ein Script ein Dokument (oder Teile davon) vollständig aufbaut, oder ob man das Objekt beeinflussen will, an dem der Benutzer gerade arbeitet.
Ein typisches Beispiel für die erste Situation ist eine Datenbankanbindung, bei der z.B. auf Basis ausgewählter Datensätze in FileMaker bestimmte Layout-Seiten aufgebaut werden. Ein einfaches Beispiel für die zweite Situation: Man braucht eine Anweisung, die ein ausgewähltes Rechteck mit einem Schatten versieht.
Zwei Techniken gehen auf die aktuelle Tätigkeit des Benutzers ein:
a) Bei einer Reihe von Aktionen, die eigentlich ein klares Ziel brauchen, darf dieses Ziel im Script fehlen. RagTime wählt das Ziel dann bezogen auf das Objekt, an dem der Benutzer gerade arbeitet.
b) Das selection Objekt kann ausgewertet werden.
In folgendem Script-Fragment
tell application "RagTime 6.5"
     set Auswahl to selection of window 1
     -- weiterer Script-Code
end tell
ist es im “weiteren Script-Code� nicht immer dasselbe, ob “selection� benutzt wird oder die Variable “Auswahl�. “selection� greift direkt auf ein RagTime-Objekt zu. Beim Zuweisen der Variablen wird das Objekt in eine Referenz aufgelöst und diese im Script abgelegt. Der Zugriff über “Auswahl� ist indirekter. In den meisten Fällen ist das Resultat bei beiden Zugriffen identisch. Im Abschnitt über die Ausrichtung von Bildern gab es einen Fall, der zu verschiedenen Resultaten führt.
Betrachten wir den Fall etwas detailierter: Angenommen war ein Dokument mit einem Bild. Das Bild ist in zwei Containern installiert. Der Anwender hat das Bild in einem der Container ausgewählt.
Script-Variante 1:
tell application "RagTime 6"
     align picture selection of window 1 horizontally at left side
end tell
Script-Variante 2:
tell application "RagTime 6.5"
     set Auswahl to selection of window 1
     align picture Auswahl horizontally at left side
end tell
In der ersten Variante wird das Bild nur in dem Container nach links ausgerichtet, in dem es ausgewählt ist. In der zweiten Variante wird es in allen Containern ausgerichtet. In der “set Auswahl...�-Zeile wird selection in einen Bezug der Form “picture "Bild 1" of document id 1� aufgelöst (das Bild heißt bei Ihnen ggf. anders). Die “align picture�-Anweisung wird dann an diese Bildkomponente geschickt. Diese Anweisung richtet das Bild an allen Stellen aus, an denen es installiert ist.
Dieser Text würde sehr lang werden, wenn wir alle Fälle behandelten, in denen sich die beiden Formen in der Wirkung gleichen und in welchen nicht. Für die eigene Arbeit mit dem selection-Objekt sollte nur klar sein: Technisch sind die beiden Zugriffsformen immer verschieden. Wenn also im konkreten Fall die eine das falsche tut, probiert man die andere.
Im Regelfall ist der direkte Zugriff auf selection in der Wirkung dichter am Aufruf einer Anweisung in der RagTime-Benutzungsoberfläche.
Änderungen in AppleScript haben leider dazu geführt, dass sich das sogenannte "Default Targeting" unterschiedlich verhält, abhängig davon, ob das Script im Programm selbst läuft oder aber es von außen (Script Editor) steuert. Mit "Default Targeting" ist gemeint, welches Ziel in einem Programm benutzt wird, wenn eine klare Zielangabe fehlt. In vielen Fällen wird dann die bestehende Auswahl ausgewertet. Die für das Programm gültige Auswahl steht aber nicht mehr zur Verfügung, wenn RagTime im Hintergrund ist.
Gehen wir von folgender Situationsannahme aus:
In RagTime ist ein Dokument mit mehreren Seiten geöffnet. Auf einer der Seiten ist ein Grafik-Objekt angeklickt, oder aber, es wurde zuletzt in den leeren Seitenbereich geklickt.
In RagTime 6.5 funktioniert dann folgendes Script:
make new rectangle with data {100, 100, 200, 300}
(Das »tell application "RagTime 6.5"« kann innerhalb von dem RagTime-Script-Editor natürlich fehlen. Das Script ist so vollständig.)
Ohne irgend eine Angabe, wo in einem Dokument dieses Rechteck angelegt werden soll, bestimmt die aktuelle Auswahl das Ziel. Das Rechteck wird auf der Zeichenfläche angelegt, die (oder in der) gerade die aktuelle Auswahl steht. Das ist zum Beispiel die Seite oder Zeichnung, in deren leeren Bereich zuletzt geklickt wurde. Oder aber die Seite / Zeichnung, in der gerade ein beliebiges Grafikobjekt ausgewählt ist.
Vom AppleScript Editor aus funktioniert diese Technik nur, wenn RagTime zuerst in den Vordergrund geholt wird:
tell application "RagTime 6.5"
     activate
     make new rectangle with data {100, 100, 200, 300}
end tell
Lässt man das »activate« weg, führt das Script in eine Fehlermeldung.
Um diese Technik noch etwas weiter zu illustrieren: Folgendes Script zieht Hilfslinien genau durch den Mittelpunkt des ausgewählten Objekts:
tell application "RagTime 6.5"
     activate
     set {X, Y} to position of selection
     make new vertical guide with data X
     make new horizontal guide with data Y
end tell
(Wiederum würde innerhalb von RagTime folgendes Script dasselbe tun:
set {X, Y} to position of selection
make new vertical guide with data X
make new horizontal guide with data Y
)
Im ersten Schritt wird die Position des Auswahl-Objekts ausgelesen. Da die Anweisung an RagTime geht (und nicht etwa an window 2 u.ä.) ist dies immer die Auswahl im aktuellen Dokument.
Die beiden folgenden Anweisungen legen Hilfslinien in der gerade benutzten Zeichnungsumgebung an. Das ist immer die Umgebung, in der das Objekt gerade ausgewählt ist.
Kriterium dafür, dass die Zielangabe fehlt, ist die fehlende “at�-Klausel. Selbst, wenn der “make new...�-Ausdruck in einem tell-Block steht, wird er als “Ohne Zielangabe� behandelt, wenn das “at� fehlt. Folgende Beispiele
tell application "RagTime 6.5" -- Fehlerbeispiel
     activate
     make new rectangle with data {100, 100, 200, 300} at beginning
end tell
Das Script führt bei Ausführung in eine Fehlermeldung. Wenn die “at�-Klausel vorhanden ist, muss das Ziel vollständig gegeben sein.
Für das nächste Beispiel wieder eine Situationsannahme: Sie haben ein Layout mit drei Seiten vor sich und ein Objekt auf Seite 3 angeglickt:
tell application "RagTime 6.5"
     tell page 1 of layout 1 of document 1
          activate
          make new rectangle with data {100, 100, 200, 200}
          make new rectangle with data {100, 100, 350, 350} at beginning
     end tell
end tell
Bei dem ersten (kleineren) Rechteck fehlt die “at�-Klausel. Die Anweisung geht an die aktuelle Zeichnungsumgebung und das Rechteck erscheint auf der angeklickten Seite 3 trotz des umgebenden “tell�.
Das zweite Rechteck hat eine “at�-Klausel und der umgebende tell-Block gibt das Ziel vollständig an. Das Rechteck wird auf Seite 1 erzeugt.
Selbst, wenn in dem “tell� ein “of document 2� stünde, würde das erste Rechteck in Dokument 1 angelegt werden, das zweite aber in Dokument 2. Deutlich sieht man den Unterschied, wenn man sich im AppleEvent Log ansieht, wie die Kommunikation mit RagTime abläuft:
tell application "RagTime 6.5" -- Ausschnitt aus AppleEvent Log
     activate page 1 of layout 1 of document 1
     make new rectangle with data {100, 100, 200, 200}
     --> rectangle 1 of page 3 of layout "Layout 1" of document id 1
     make new rectangle with data {100, 100, 350, 350} at beginning of page 1 of layout 1 of document 1
     --> rectangle 1 of page 1 of layout "Layout 1" of document id 1
end tell
Arbeitet man mit dem selection-Objekt, kann es leicht zu allen möglichen Fehlern im Ablauf des Scripts kommen: Die aktuelle Auswahl des Benutzers ist evtl. gar nicht geeignet für die Aktionen des Scripts. Zwei Techniken bieten sich an: Wenn das Script nur für eine ganz bestimmte Art von Objekten geeignet ist, fragt man zunächst die Klasse der Auswahl ab und arbeitet nur im geeigneten Fall weiter. Wird mit einer Eigenschaft gearbeitet, die viele unterschiedliche Objekte haben können (position ist ein Beispiel), und ist das Script für (fast) alle dieser Objekte geeignet, ist ein try nützlicher.
Ein Beispieldokument enthalte ein Rechenblatt namens “Rechenblatt 1�. Wenn der Benutzer Text ausgewählt hat, soll dieses Rechenblatt am Anfang der Auswahl eigefügt werden.
tell application "RagTime 6.5"
     set textAuswahl to selection of window 1
     set Tabelle to a reference to table "Rechenblatt 1" of document 1
     if (class of selection of window 1) is text then
          set insertion point before textAuswahl to Tabelle
     end if
end tell
Ist irgend etwas anderes als Text ausgewählt, wird der if-Teil nicht ausgeführt. Dennoch sollte man auch in diesem Fall ein try erwägen. Es gibt immer Fälle, in denen das Script Fehlermeldungen auslöst und die man vergisst. Hier wären folgende Fälle betroffen: Die Einfügemarke steht in einem leeren Text, im Rechenblatt in einem Mehrzeilertext oder in einem grafischen Text.
Ein vorangehendes Beispiel hat Hilfslinien durch ein ausgewähltes Objekt gezeichnet. Dies ist ein typisches Beispiel für den Einsatz von try: Die Eigenschaft position haben Rechtecke, Beziérkurven, Punkte von Beziérkurven... In allen Fällen ist die folgende Anweisung, Hilfslinien durch die Position der Auswahl zu zeichnen, sinnvoll. Ist aber Text oder eine Rechenblattzelle ausgewählt, ist das Script nicht sinnvoll und führt in einen Fehler. Hier ist try die beste Technik:
tell application "RagTime 6.5"
     try
          set {X, Y} to position of selection of window 1
          activate
          make new vertical guide with data X
          make new horizontal guide with data Y
     end try
end tell
Wenn das ausgewählte Objekt die property position gar nicht hat oder aber in der benutzten Umgebung keine Hilfslinien möglich sind (z.B. ein Objekt einer Infografik ist ausgewählt), bricht die Ausführung einfach ab ohne durch eine unverständliche Fehlermeldung zu irritieren. In allen Fällen, in denen aber sinnvoll die Hilfslinien gezeichnet werden können, wird die Anweisung ausgeführt. Hält man eine Warnung für sinnvoll, kann man natürlich eine eigene Meldung erzeugen: Folgende Variante erzeugt eine eigene Meldung, gefolgt von der Originalmeldung:
property Fehlertext1 : "Es konnten keine Hilfslinien angelegt werden. Vermutlich ist kein geeignetes Objekt ausgewählt."
property Fehlertext2 : "AppleScript-Fehler: Nummer "
tell application "RagTime 6.5"
     try
          set {X, Y} to position of selection of window 1
          activate
          make new vertical guide with data X
          make new horizontal guide with data Y
     on error Meldung number Fehlernummer
          display dialog Fehlertext1 & return & return & Fehlertext2 & ¬
               Fehlernummer & ", " & Meldung buttons {"OK"} default button 1
     end try
end tell
Zum Abschluss noch eine Variante, die eher traditionellem “exception handling� entspricht: Statt einer eigenen Meldung wird die normale AppleScript-Meldung hochgereicht, aber ergänzt um die eigene Information:
property Fehlertext : "Vermutlich können durch das ausgewählte Objekt keine Hilfslinien gezogen werden."
tell application "RagTime 6.5"
     try
          set {X, Y} to position of selection of window 1
          activate
          make new vertical guide with data X
          make new horizontal guide with data Y
     on error Meldung number Fehlernummer
          error Meldung & return & Fehlertext number Fehlernummer
     end try
end tell
Beim Arbeiten mit Variablen, denen das selection-Objekt zugewiesen wurde, kann auch die Änderung der Auswahl durch eine Script-Aktion oder aber die Änderung ihres Bezugs eine Falle stellen.
Folgende Script-Varianten gehen davon aus, dass ein Rechteck ausgewählt ist.
Variante 1
tell application "RagTime 6.5"
     set Auswahl to selection of window 1
     make new rectangle at before Auswahl with data {50, 100, 150, 300}
     set color of Auswahl to {cyan:10, magenta:50, yellow:80, black:5}
end tell
Variante 2
tell application "RagTime 6.5"
     set Auswahl to selection of window 1
     make new rectangle at before Auswahl with data {50, 100, 150, 300}
     set color of selection of window 1 to {cyan:10, magenta:50, yellow:80, black:5}
end tell
In Variante 1 wird das neu angelegte Rechteck orange gefärbt, in Variante 2 das ausgewählte. Grund: Die Variable Auswahl enthält eine Referenz auf das Rechteck nach Index. Dadurch, das vor dem ausgewählten Rechteck ein neues angelegt wurde, hat dieses neue Rechteck den Index, den vorher das ausgewählte hatte. “Auswahl� zeigt deshalb jetzt auf das neue Rechteck.
Besonders bei Texten kann sich die Auswahl von Buchstaben durch Hinzufügen oder Löschen ändern. Ein Beispielscript soll vor und nach der Auswahl einen Bindestrich einfügen.
tell application "RagTime 6.5"-- Unerwartetes Resultat
     set Auswahl to selection of window 1
     set insertion point before Auswahl to "-"
     set insertion point after Auswahl to "-"
end tell
Durch das Einfügen des ersten Bindestrichs hat sich die Anzahl der Buchstaben verändert. Der zweite wird deshalb einen Buchstaben zu früh eingefügt.
In einen Fehler läuft auch die naheliegende Idee, direkt auf selection zu arbeiten:
tell application "RagTime 6.5"-- Fehlerhaftes Beispiel
     set insertion point before selection of window 1 to "-"
     set insertion point after selection of window 1 to "-"
end tell
Einer der Fälle, in denen sich der direkte und der indirekte Zugriff auf die Auswahl unterscheiden.
Eine Lösungsmöglichkeit ist, in der ersten Variante die Auswahl erneut abzufragen:
tell application "RagTime 6.5"
     set Auswahl to selection of window 1
     set insertion point before Auswahl to "-"
     set Auswahl to selection of window 1
     set insertion point after Auswahl to "-"
end tell
In Fällen wie diesem, in dem die Aktion die Anzahl der Buchstaben auf jeden Fall vergrößert, kann man natürlich auch einfach die Reihenfolge beim Einsetzen ändern und von hinten nach vorn arbeiten:
tell application "RagTime 6.5"
     set Auswahl to selection of window 1
     set insertion point after Auswahl to "-"
     set insertion point before Auswahl to "-"
end tell
Wie in dem einführenden Teil zu Programmobjekten beschrieben, kann man in RagTime und unterhalb von RagTime über Fenster das Objekt selection ansprechen. In Dokumenten kann man das Objekt selection nicht ansprechen.
Seit einiger Zeit ist allerdings die für das Programm gültige Auswahl nur im Script-Zugriff, wenn RagTime im Vordergrund ist. Lässt man ein Script in RagTime laufen, ist das immer der Fall. Nicht aber, wenn man den Apple Script Editor im Vordergrund hat und das Script von dort aus laufen lässt.
tell application "RagTime 6.5" -- Problembeispiel
     set A to selection
end tell
führt zu einer Fehlermeldung. Hingegen funktioniert folgende Variante korrekt:
tell application "RagTime 6.5"
     activate
     set A to selection
end tell
Wird explizit ein Fenster angesprochen, kann das activate fehlen:
tell application "RagTime 6.5"
     set A to selection of window 1
end tell
führt zu keinem Fehler. Folgendes Script eignet sich zum Experimentieren, wenn man sich im Script Editor anschließend das Resultat ansieht:
tell application "RagTime 6.5"
     activate
     set A to selection
     set B to selection of window 1
     set C to selection of window 2
     {A, B, C}
end tell
Nehmen wir folgende Situation an: Zwei Dokumente sind geöffnet, im hinteren ist etwas Text ausgewählt, im forderen ein Rechteck auf einer Seite. Dann wird das Resultat dieses Scripts etwa wie folgt aussehen:
{
rectangle 1 of page 1 of layout "Layout 1" of document id 2 of application "RagTime 6.5",
rectangle 1 of page 1 of layout "Layout 1" of document id 2 of application "RagTime 6.5",
text from character 1 to character 10 of contents of text flow "Text 1" of document id 1 of application "RagTime 6.5"
}
Die ersten beiden Abfragen, selection und selection of window 1, liefern dasselbe Resultat, die Auswahl im ersten Dokument. Die Variable C enthält die Auswahl im zweiten Dokument.
Wird nun im forderen Dokument das Fenster Schriftvorlagen geöffnet und “Standardschrift� in der Liste ausgewählt, liefert das Script folgendes Resultat:
{
character style sheet "Standardschrift" of document id 2 of application "RagTime 6.5",
character style sheet "Standardschrift" of document id 2 of application "RagTime 6.5",
rectangle 1 of page 1 of layout "Layout 1" of document id 2 of application "RagTime 6.5"
}
In dieser Variante gehören die beiden ersten Fenster zu Dokument 1: Das Schriftvorlagen-Fenster und das Layout-Fenster. Variable A und B enthalten wieder dasselbe. Die selection von RagTime ist immer gleich der selection des ersten Fensters von RagTime. C enthält jetzt die Auswahl in dem Layout-Fenster von Dokument 1.
Wenn ein Gruppierungs-Objekt angelegt werden soll, muss ein Ziel angegeben werden, die Anweisung direkt an RagTime zu schicken, funktioniert nicht.
Es bietet sich folgende Technik an: Als Ziel kann “at after� bezogen auf das direkte selection-Objekt benutzt werden. Als Datenangabe kann das einer Variable zugewiesene selection-Objekt genutzt werden:
tell application "RagTime 6.5"
     set Auswahl to selection of window 1
     tell window 1
          make new drawing group at after selection with data Auswahl
     end tell
end tell
Dieser Code gruppiert die ausgewählten Zeichnungsobjekte. Die Gruppe ist danach nicht ausgewählt. Will man das normale Programm-Verhalten haben, bei dem nach dem Gruppieren die Gruppe ausgewählt ist, nimmt man folgenden Code:
tell application "RagTime 6.5"
     set Auswahl to selection of window 1
     tell window 1
          set Gruppe to (make new drawing group at after selection with data Auswahl)
          select Gruppe
     end tell
end tell
Eine Gruppe wird einfach mit ungroup wieder aufgelöst:
tell application "RagTime 6.5"
     ungroup selection of window 1
end tell