今回からはシステムボタンを管理するプラグインの話ね。 | |
SystemButtonPlugin クラスだよね。 | |
そう。前回もちょっと言ったけど、SystemButtonPlugin クラスを一部書き換えないといけないから、 まずは SystemButtonPlugin クラスがどうやってシステムボタンを管理してるのかを見ていくね。 | |
SystemButtonPlugin クラスって結構複雑だったような気がするんだけど…? | |
ん〜、確かにちょっと複雑かもね。 でも、やってることはそんなに複雑じゃないから、ちゃんと理解できると思うよ? |
|
そうなの? | |
うん、多分ね。 じゃ、最初は SystemButtonPlugin クラスのメンバ変数から見ていくね。 |
<SystemButtonPlugin クラスのメンバ変数>
まず、x と y は最初のボタンを表示する位置。 | |
最初のボタン? | |
このプラグインは複数のボタンを管理できるようになってるから、ボタンに順番があるんだ。 で、最初のボタンが (x, y) の位置に表示されて、 2番目のボタンは最初のボタンの右隣に表示されるように、自動的に位置が決められるの。 |
|
えっと、じゃあ、例えばボタンの幅が 100 ピクセルだったら、
最初のボタンが (510, 300) の位置に表示されて、2番目のボタンは
(610, 300) に表示されるってこと? |
|
そうそう、そういうこと。 次の foreSeen と backSeen は、 それぞれ表画面と裏画面のボタンが表示されてるかどうかを表すメンバ変数。 |
|
それって前の章で作った DatePlugin クラスの foreVisible と backVisible みたいなもの? | |
※詳しくは §4.10 参照。 | |
うん。foreSeen と backSeen の使い方も基本的に同じだよ。 | |
じゃあシステムボタンもメッセージレイヤを非表示にすると非表示になるの? | |
うん、なるよ。 ていうか DatePlugin クラスは SystemButtonPlugin クラスを意識して作ったからね。 |
|
あ、そうだったんだ。 | |
で、最後の foreButtons と backButtons は、 それぞれ表画面に表示するボタンオブジェクトと裏画面に表示するボタンオブジェクトの配列。 | |
表画面に表示する最初のボタンが foreButtons[0] ってこと? | |
ん、そうだよ。 ちなみに foreButtons = []; っていうのは foreButtons = new Array(); と同じ意味ね。 |
|
あ、そういえば… | |
ん? | |
メンバ変数が全部ここで初期化されてるけど、メンバ変数ってコンストラクタで初期化するんじゃないの? | |
あー、実はメンバ変数はこうやって普通の変数と同じように初期化できるんだ。 | |
そうなの? あ、じゃあコンストラクタで初期化するのとここで初期化するのは何か違いがあるとか? |
|
ううん、別にどっちで初期化しても同じだよ。 | |
えっ? じゃあ、メンバ変数ってどっちで初期化してもいいってこと? | |
うん。基本的にはどっちで初期化しても OK。 メンバ変数を宣言してるところで初期化する場合は、 メンバ変数が初期化されてからコンストラクタが呼び出されるようになってるんだ。 |
|
へぇ、そうなんだ。 | |
じゃ、メンバ変数についてはこんなところだから、次はコンストラクタね。 |
う〜ん、コメントが書いてあるから何となく何してるかは解るけど、 全部メソッドを呼び出してるから、メソッドの中身を見てみないとよくわからないね… | |
だね。じゃあ createButtons メソッドから見ていこっか。 | |
うん。 |
createButtons メソッドは名前の通りボタンを作るメソッド。 このメソッドでセーブ用とロード用2つのボタンを作ってるんだ。 |
|
どっちも SystemButtonLayer クラスのオブジェクトになってるね。 | |
コンストラクタの引数がどうなってるかわかる? | |
えっと、第1引数がこのボタンが所属するウィンドウで kag オブジェクトになってて、 第2引数はこのボタンの親レイヤで、createButtons メソッドの第1引数の parent になってるね。 | |
parent は表画面用のボタンを作る時は kag.fore.base になって、 裏画面用のボタンを作る時は kag.back.base になるんだ。 | |
それってボタンの親レイヤは背景レイヤになるってことだよね? | |
ん、そういうこと。 | |
あと、第3引数はボタンが押された時に呼び出されるメソッド、だったよね? | |
そ。だから、セーブ用のボタンは押された時に onSaveButtonClick メソッドが呼び出されるわけね。 ちなみに onSaveButtonClick メソッドはこうなってるよ。 |
saveBookMarkToFileWithAsk って見たことないメソッドだね。 kag.saveBookMarkToFileWithAsk(); ってことは、このメソッドって kag オブジェクトのメソッド? |
|
そだよ。 saveBookMarkToFileWithAsk メソッドは、フリーセーブモードの時に、 こういうファイル選択ダイアログボックスを表示して、栞を保存するメソッド。 |
あ〜、これってフリーセーブモードの時に、メニューの「栞をはさむ」を選択すると表示されるダイアログボックスだよね。 | |
そうそう。 メニューの「栞をはさむ」を選択すると saveBookMarkToFileWithAsk メソッドが呼び出されるようになってるんだ。 |
|
あ、そうなんだ。 | |
で、ロード用のボタンが押された時に呼び出される onLoadButtonClick メソッドも同じような感じになってるんだ。 |
今度は loadBookMarkFromFileWithAsk っていうメソッドが呼び出されてるけど、 これってやっぱりフリーセーブモードの時に、メニューの「栞をたどる」を選択するのと同じになるの? | |
うん。 loadBookMarkFromFileWithAsk メソッドはフリーセーブモードの時に、 こういうファイル選択ダイアログボックスを表示して、栞を読み込むメソッドだからね。 |
ってワケで、結局セーブ用のボタンを押すのは、メニューの「栞をはさむ」を選択するのと同じで… | |
ロード用のボタンを押すのは、メニューの「栞をたどる」を選択するのと同じってことだね。 | |
で、ボタンを作ったら createButtons メソッド の第2引数で指定されてる配列 array に追加してるわけね。 | |
この array ってどんな配列なの? | |
array は表画面用のボタンを作る時には foreButtons で、 裏画面用のボタンを作る時には backButtons になるんだ。 | |
あー、それってメンバ変数のボタンオブジェクトの配列だね。 | |
そ。で後は loadImages メソッドでボタン用画像を読み込んで、ボタン完成。 | |
セーブボタン用には "YesButton" っていう画像を読み込んで、 ロードボタン用には "NoButton" っていう画像を読み込んでるんだよね。 | |
うん。まぁ、ボタン用画像のファイル名は適当に決めていいと思うけどね。 じゃ、次は realign メソッド。 |
<realign メソッド(※コメントを追加してあります)>
これって何するメソッドなの? | |
realign メソッドはボタンを横に並べて表示するメソッドだよ。 さっき最初のボタンをメンバ変数の x と y の位置に表示して、 2番目以降のボタンは自動的に表示する位置が決められるって言ったでしょ。 |
|
うん。 | |
realign メソッドでボタンの表示位置を決めて、それぞれのボタンを決められた位置に表示するの。 | |
あ、そうなんだ。 | |
セーブ用のボタンとロード用のボタンを表示するときは count はいくつになると思う? | |
え〜っと、count は foreButtons の
count プロパティになってるから、ボタンの数ってことだよね… ってことは… 2 ? |
|
そ。つまり for ブロックの中身は i=0 と i=1 で2回実行されるわけね。 | |
i=0 の時にセーブ用ボタンの表示位置を決めて、 i=1 の時にロード用ボタンの表示位置を決めてるってことだよね? | |
ん、そうだよ。 じゃあ、i=0 の時に xpos はいくつになる? |
|
ん〜… xpos は btn_x + x で、
btn_x は最初 0 になってるよね… あと、x は 510 に初期化されてるから、 0 + 510 で 510 かな。 |
|
ん、そうだね。 じゃあ、セーブ用ボタンはどの位置に表示される? |
|
セーブ用のボタンって、setPos メソッドで位置を設定してるんだよね? | |
そだよ。あと、表画面用のボタンも裏画面用のボタンも setPos メソッドの引数は同じだから、 同じ位置に配置されるってことだね。 | |
じゃあ… y は 300 に初期化されてるわけだから、 setPos(xpos, y) は setPos(510, 300) ってことになるから、 セーブ用のボタンは (510, 300) の位置に表示されるのかな? | |
うん、正解。 それじゃセーブ用のボタンの幅、つまり obj.width が 50 ピクセルだったとしたら、ロード用のボタンはどこに表示されると思う? |
|
ん〜っと…ロード用ボタンの xpos を計算する前に、
btn_x += obj.width; が実行されるよね。 obj.width が 50 ってことは、 btn_x は 50 になるよね。 |
|
だね。 | |
じゃあ今度は xpos が 50 + 510 で 560 になって、 y はそのままだから、ロード用のボタンは (560, 300) に表示されるんじゃないかな? | |
そ。つまり、ロード用のボタンはこんなふうにセーブ用のボタンの右隣に表示されるってワケ。 |
<セーブ・ロードボタンの表示位置>
で、ロードボタンの位置を設定した後は btn_x にロード用ボタンの幅が加算されるから、 もしボタンが3つあったとしたら、3番目のボタンはロード用ボタンの右隣に表示されるわけね。 | |
ってことは、ボタンはずっと横につながって一列に表示されるってことだよね? | |
ん、そういうこと。 | |
なるほどね〜。 あ、一つ質問! |
|
ん? | |
absolute っていうプロパティ?…も設定してるみたいだけど、 この absolute って何なの? | |
absolute プロパティはレイヤの重ね合わせの順序を表すプロパティだよ。 | |
じゃあそれって image タグの index 属性みたいなもの? | |
みたいなもの、っていうか absolute プロパティと index 属性は全く同じものだよ。 | |
え、そうなの? | |
うん。KAG の属性と TJS のプロパティで違う名前になってるだけ。 | |
へぇ、そうなんだ。 | |
メッセージ履歴を表示するレイヤの absolute プロパティの値が 2000000 だから、 ボタンの absolute プロパティを 2000000-3 に設定することで、 ボタンをメッセージ履歴より奥に表示するようにしてるわけだね。 | |
3 引くのって何か意味があるの? | |
うーん、どうだろ。別に 3 じゃないといけないってコトはないんじゃないかな。 | |
じゃ別の値でもいいってこと? | |
うん、別の値の方がいいって思うんだったら変えても OK。 まぁでも特に問題がなければこの値にしといていいんじゃない? |
|
そっか、わかった。 | |
それじゃこれで realign メソッドは一通りチェックできたから、 次は setObjProp メソッドを見ていこっか。 |
シンプルなメソッドだね。 | |
見た目はね〜。 | |
えっ? それってどういうこと? | |
実はこのメソッド、単純そうに見えてちょっとややこしいんだ。 | |
え、そうなの? | |
コンストラクタでこんなふうに setObjProp メソッドが呼び出されてるでしょ。 |
このときに setObjProp メソッドのスクリプトがどんなふうに実行されるかわかる? | |
引数の array と member と value がそれぞれ foreButtons と 'visible' と…え〜っと、これって確か false になるんだよね? | |
そ。foreSeen = false を第3引数に指定すると、 setObjProp メソッドが呼び出される前にまず foreSeen に false が代入されて、 その結果この式全体の値が false になるから、 setObjProp メソッドが呼び出される時には第3引数は false になって、 value も false になるよ。 | |
な、なんかややこしいね… | |
まぁ先に foreSeen = false; を実行してから setObjProp(foreButtons, 'visible', foreSeen); を実行するって考えればいいと思うよ。 | |
なるほどね。 えっと、array の count プロパティは 2 だから、 for ブロックの中身は2回実行されるよね。 |
|
i の初期値が array.count-1 になってて、
i が 0 以上の間 i をデクリメントするから、
今回は i=1, i=0 の順になって、ロードボタンが先で、セーブボタンが後に設定されるね。 で、i=1 の時は… |
|
引数の値を当てはめると、foreButtons[1]['visible'] = false; になるよね…? | |
ん、そうだね。 | |
なんか見たことない書き方なんだけど…? | |
foreButtons[1] が何を指してるかは解るよね? | |
ロード用ボタンオブジェクトだよね? | |
そうそう。じゃあ、さっきの realign メソッド みたいに、 obj っていう変数を作って、obj = foreButtons[1]; って感じで obj にボタンオブジェクトへの参照を代入したとするね。 | |
うん。 | |
そしたら、foreButtons[1]['visible'] は obj['visible'] って表せるでしょ。 | |
そだね。 | |
この書き方って前に見たことない? | |
え? う〜ん…… あ、そういえば辞書配列って確かこんな書き方できなかったっけ? |
|
ん、それそれ。 辞書配列だと『辞書配列名['要素名']』って書くのと 『辞書配列名.要素名』って書くのは同じだったよね。 |
|
うん、そうだったよね。 | |
実は普通のクラスのオブジェクトもこういう書き方ができるんだ。 | |
え、そうなの? | |
うん。つまり、obj['visible'] って書くのと、 obj.visible って書くのは同じ意味になるんだ。 | |
あ、じゃあ obj['visible'] でオブジェクトの visible プロパティを設定できるんだ? | |
ん、そのとーり。 だから foreButtons[1]['visible'] = false; で表画面のロード用ボタンの visible プロパティを false に設定してたってワケ。 |
|
なるほどね〜。 | |
つまり、setObjProp メソッド は、 array っていう配列に含まれてるオブジェクトの member っていうプロパティの値を value に設定する、っていうメソッドなの。 | |
じゃあ、コンストラクタで setObjProp メソッド を呼び出してるのって、 表画面と裏画面の全部のボタンの visible を false にしてる、 ってコトなんだよね? | |
そういうこと。 これでコンストラクタでやってることは解ったよね。 |
|
最初に createButtons メソッド を呼び出してボタンを作って、 それから realign メソッド を呼び出してボタンを横に並べて、 最後に setObjProp メソッド を呼び出してボタンの visible を false にしてるんだよね。 | |
ん、OK。 んじゃ今回はここまでにして、残りのメソッドは次回見ていくことにするね。 |
|
は〜い! | |
それじゃ、また次回ね! |