グループとバックグラウンド

 RunRev を使い始めて最初に「あれ?」と思ったのがバックグラウンドでした。メニューのどこにもバックグラウンドに関する項目がありません。なのに HyperCard のスタックを RunRev で開くと、バックグラウンドにあったものがちゃんと再現され、バックグラウンドスクリプトも機能します。

 ここでは RunRev のグループとバックグラウンドについて、気が付いたことを並べてみます。「 Tip of the Week 5 」と、Encyclopedia の「 About Groups and backgrounds 」も併せて読んで下さい。

−−

 まず基本的に、RunRev には「バックグラウンド」というオブジェクトはありません。代わりに「グループ」という強力な概念がサポートされています。グループとは、「複数のオブジェクトをまとめたオブジェクト」です。

 グループをバックグラウンドのように扱うことも出来ますが、これは RunRev ではむしろ特殊なモードです。まずはグループがどういうものかを説明し、それからBG動作について補足します。

−−

 グループを作るには、ポインタカーソル(矢印カーソル)で複数のオブジェクトを選択して、ツールバーの Group ボタンをクリックします。オブジェクト1つだけでもグループに設定出来ます。カード上にいくつでもグループを作ることが出来、またグループがグループを内包することも出来ます。
 ツールバーの Group ボタンの代わりに Object メニューの Group Selected も使えます。

 グループには番号やIDがあり、また名前を付けることが出来ます。ひと塊のオブジェクトを一発で移動/複製できるので、カードをデザインする時に重宝します。また実行時にも一群のインターフェースを簡単に Show/Hide 出来るので、分かりやすいインターフェースを作りやすいでしょう。

 グループに縦横のスクロールバーを付けることが出来ます。これはインターネットブラウザのフレーム表示のように、「カード内の一部だけをスクロール」出来るようなインターフェースを作るのに使えます。

 グループを解除するには、グループを選択してツールバーの Group ボタンをクリックします。この時グループに設定されていたプロパティやスクリプトは失われます。アンドゥ出来ないので気を付けて下さい。ただしカードを移動する前であれば、再度グループ化してそれらを復活させることも出来ます。

−−

 グループ内のオブジェクトを編集するには2種類のモードがあります。

 ツールバーの SGC がハイライトしていないモードでは、ポインタカーソルで「グループを」選択できます。グループを選択してツールバーの Edit Group をクリックすると、丁度 HyperCard のバックグラウンド編集のようなモードになり、グループに含まれているオブジェクトだけが見えるようになります。ここで個々のオブジェクトを編集したり、追加や削除が出来ます。グループ編集モードを抜けるには再度 Edit Group ボタンをクリックします。
 ツールバーの SGC ボタンのハイライト状態はちょっと見辛いです。代わりに Edit メニューの Select Grouped Object も使えます。メニューにチェックを付けた状態が SGC オンです。
 またツールバーの Edit Group の代わりに Object メニューの Edit Group も使えます。グループ編集モードを抜けるには Stop Editing Group メニューを使います。
 ちなみにこのモードでも、Command キー(マック)や Alt キー( Windows / Unix )+オブジェクトのクリックで、グループ内の個々のオブジェクトを選択することが出来ます。


 ツールバーの SGC がハイライトしているモードでは、ポインタで個々の「オブジェクトを」選択/編集出来ます。グループ化されたオブジェクトもそうでないものも区別しません。これは HyperCard とも SuperCard とも違う、独特のモードです。

 「グループを」選択/編集したい場合は SGC オフの方がいいでしょう。グループそのもののプロパティやスクリプトを操作するにはこれを使います。またグループ編集モードに入ってグループ内のオブジェクトを安全に追加/削除することが出来ます。

−−

 全てのオブジェクトは button "abc" のように指定します。 HyperCard や SuperCard のように、card button "abc" と書く必要はありません。 HyperCardスタックをコンバートした場合に備えてこの書き方もサポートされていますが、Transcript で新たにスクリプトを書く場合は、card や background などのレイヤー名は付けないのが無難です。

 グループ内にあるオブジェクトを指定するには button "abc" of group "myGroup" のようにグループ名を付けます。ちなみに Transcript では owner プロパティが拡張されており、例えばこの button "abc" の the owner は、group "myGroup" を指します。

−−

 グループに「グループスクリプト」を書くことが出来ます。グループ内のオブジェクトとグループの関係は、丁度カードオブジェクトとカードのような関係になります。つまりメッセージの流れはこうです。
  オブジェクト − グループ − カード − スタック

 メッセージは、そのオブジェクトが属するグループにだけ流れます。仮に他のグループが存在しても、そこにはメッセージは流れません。
           グループ1\
  オブジェクト − グループ2 − カード − スタック
           グループ3/

 グループが他のグループに内包されていると、上位のグループにもメッセージが流れます。これは丁度カードとBGの関係に似ています。
  オブジェクト − グループB − グループA − カード − スタック

 ここでも気を付けたいのは、あくまで「グループAへ」メッセージが継承されるのであって、「グループA内のオブジェクト」にはメッセージが流れないことです。グループA内の各オブジェクトはグループBと同階層であり、メッセージパスには含まれません。
           オブジェクト\
  オブジェクト − グループB − グループA − カード − スタック
           オブジェクト/
 図で描くと当たり前に見えますが、ボタンなどの配置を考える時に案外勘違いし易い部分です。

−−

 さて以上が「グループ」の基本的な動作ですが、グループには background behavior というプロパティがあります。直訳すると「バックグラウンド挙動」ですね。これにチェックを入れると、ちょっと独特の動作をするようになります。

 面倒を避けるために、background behavior を true にしたグループを、以後「BG」と呼びます。またそのBG内のオブジェクトを「BGオブジェクト」と呼ぶことにします。

−−

 BG内のオブジェクトでメッセージが発生した場合、メッセージ継承階層は普通のグループと変わりません。つまりこんなです。
  オブジェクト − BG − カード − スタック

 BGが「カード上に乗っている」状態です。これは HyperCard や SuperCard と決定的に違いますから、継承順位が問題になるスクリプトでは注意が必要です。

 グループはカード内にいくつも作れますから、それぞれのグループをBGに設定すると、カード上にいくつものBGが存在するという状況が生まれます。そうであってもメッセージ継承階層は変わりません。オブジェクトから流れてきたメッセージはそのオブジェクトが属するBGにだけ届き、カードに流れて行きます。他のBGはそのメッセージを受け取ることはありません。
           BG3\
  オブジェクト − BG2 − カード − スタック
           BG1/

 もちろんBG内にBGやグループを内包することも出来るので、その状態であれば上位のBGやグループにもメッセージは流れます。
  オブジェクト − BGb − BGa − カード − スタック


 面白いことに、BGに属さないオブジェクトで発生したメッセージ(例えばカード上のボタンや、カード自身で起きたイベント)は、カード上のBGにも流れます。
  オブジェクト − カード − BG − スタック

 BG内のオブジェクトでメッセージが発生した時は「カードにBGが乗っている」ような経路でしたが、カード上のオブジェクトでメッセージが発生すると「BGにカードが乗っている」ような振る舞いをするわけです。恐らく HyperTalk との互換性のための措置と思いますが、厳密に考えると結構危ない仕様です。

 更に複数のBGがあると、カードで発生したメッセージは、カード上の手前にある(番号が大きい)BGから順に、奥にある(番号が若い)BGへと流れていきます。
  オブジェクト − カード − BG3
                  |
                 BG2
                  |
                 BG1 − スタック

 しかしBGで発生したメッセージは、他のBGには継承されません。
  BG3\
  BG2 − カード − スタック
  BG1/

 グループ内で発生したメッセージとカード上で発生したメッセージ、そして単なるグループとBGとでは、継承経路が全く異なることになります。BGとグループが混在するとさらにややこしくなります。素直なスクリプトならまず問題になりませんが、pass を使って複数のオブジェクトでメッセージを処理するスクリプトでは、十分な注意が必要だと思います。
 ちょっと実験。 "pass" ではなく "send to this card" を使って、HyperCard や SuperCard のメッセージ継承順位を再現することが出来るのではないか? 
  (予想) オブジェクト -send- カード − BG2 − BG1 − スタック
 結果はもっと複雑なことになりました。興味ある方は試してみて下さい。実用は諦めた方が良さそうです(笑)

−−

 RunRev のBGはグループの一種ですから、基本的には「複数のオブジェクトをまとめたもの」です。ところが HyperCard では「オブジェクトは何も無く、ただスクリプトがあるだけ」というバックグラウンドが存在します。

 このようなスタックを RunRev にコンバートすると、カード左上に点のようなオブジェクトが現れます。これが「スクリプトしか持たないBGグループ」であると気付くのに、私は少し時間がかかりました。

−−

 RunRev のBGも一応バックグラウンドですから、「複数のカードに割り当てる」機能があります。そう、BGにカードが乗っているのではなく、カード上にBGがあるのでもなく、カードにBGを「割り当てる」のです。

 グループを作ったあとに新しいカードを作っても、そこにグループはありません。当たり前です。ところが「BG」を作ったあとにカードを作ると、そのカードにもBGが再現されます。なるほどバックグラウンド風。

 既存のBGを他のカードに適用させるには、Object メニューの Place Group を使います。このサブメニューから選んだBGが、現在のカードに適用されます。またBGをカードから除外したい場合は、グループを選択してから Remove Group メニューを実行します。

 これらの操作はBGの「適用」をコントロールしているだけです。まぁ一種のリンクみたいなもんですね。コピー/ペーストではBGが複製されてしまいますし、削除したらBGそのものがスタック上から消滅します。これはうっかりやりがちですから、気を付けた方がいいでしょう。

 複数のカードにBGを割り当てたい時は、View メニューの Application Overview が便利に使えます。スタック(トップに見えている「スタックファイル」ではなく、左側のトライアングルを開いた時に現れるウィンドウアイコンの「スタック」)を選択して、Overview ウィンドウ右上のトライアングルを開くと、ウィンドウが広がって色々出来るようになります。
 左のリストから Goups (個々のグループではなく、Goups と書かれたラベル)を選択して、パレット下部中央にあるスライダーボタンをクリックすると、グループのリストが表示されます。ここでグループを選択して、ウィンドウ上部にある Place ボタンから一気にグループのプレースが出来ます。
 パレット下部のスライダーボタンは「ドラッグ」するのではなく「クリック」するものです。ドラッグすると暴走することがあるのでご注意。

 Overview ウィンドウでは、カードとグループが並んでリストされます。これは興味深いです。つまりグループはスタックに従属するオブジェクトであり、カード上に Place することはできても、そこに見えているのは単なる影、一種のリンクだということになります。 HyperCard や SuperCard のような、「見えているものはそこに存在する」という素直なオブジェクトイメージは捨てねばなりません。

−−

 実は複数のカードに割り当てる機能はBG特有のものではありません。普通のグループでも全く同じ事が出来ます。

 結局BGに特有なのは、新規カードを作った時に自動的に Place されることと、一部のメッセージ継承経路が異なることだけと言うことになります。

−−

 複数のカードでグループを共有するようになると、ヤヤコシイ問題が起きるようになります。例えばいくつかのカードで既に使われているグループを、他のグループに入れようとする時です。これは結果として「グループの一部だけを他のカードと共有する」という矛盾を引き起こします。
  [カード固有のオブジェクト[各カードで共有されるグループ]]
そのため RunRev は「一旦グループを解除してから作り直すよ」という警告を出します。ここでOKを押すと、既存のグループを一旦解除してから新しいグループが作られます。この時それまでのグループのプロパティやスクリプトは失われ、各カードへの Place 状態もリセットされます。つまりゼロからやり直しです。

 カード一枚だけで作業している時は気づきにくい問題ですが、こうした矛盾は様々なケースで起こり得ます。グループを操作するときは、そのグループが他のカードでも使われている可能性があることを念頭に置いて、少し注意しながら作業した方がいいでしょう。またグループ操作は SCG オフ(マウスでグループを選択して Edit Group でグループ内を編集する)で行うのが確実です。

−−

  RunRev の Transcript ではオブジェクト名に card や background などを付けずに、button "abc" のように書きます。BG内にあるものはそのグループ名を添えて button "abc" of group "myBG" とします。

 時に、プロパティウィンドウのオブジェクト名に、"background" や "card" のようなレイヤー名が付いていることがあります。そしてこのオブジェクトの the long name プロパティも、やはり bkground button "abc" のようになっています。このオブジェクトを指定する時は cd/bg のレイヤー名が必要になります。

 これは HyperCard スタックを RunRev スタックに変換した時に起きる特有の現象です。 RunRev には元々 cd/bg の区別が無いので、このようにして HyperTalk との互換性を維持しています。このことについては HypercardToRunrev にも書かれています。

 この cd/bg の区別が煩わしい時は、set the HCAddressing of this stack to false を実行すると、オブジェクト名から "background" や "card" のようなレイヤー名を消すことが出来ます。ただしスクリプト側は cd/bg を付けた指定になったままですから、これは手作業でひとつづつ修正しなければなりません。


UDI
2002.09.16
2002.12.21

inserted by FC2 system