Kuler (Kuler@Labs) がアップデートされました。RSS への対応や UI の変更等がされています。昨日発表された Illustrator CS3 との連携もできるようです。
さて、前回の Apollo ブラウザの記事で ”戻る” ボタンに関する修正を入れたおかげでコードがぱっと見では分かり辛くなってしまいました。そこで、ちょっとアプリケーションの構造を見直してみたいと思います。
ActionScript コンポーネントの作成
まずは、履歴管理に関する機能を外部クラス化してみます。
新しく作成するクラスは PreviousLocatons という名前にして、履歴の取り出しと追加を行うために以下のようなメソッドを持たせることにします。
public class PreviousLocations {
public function popLocation():String {} // 履歴の取り出し
public function pushLocation(location:String):void {} // 履歴の追加
}
早速ファイルを作成してみましょう。例によって Ctrl-n を押してダイアログウインドウを開いたら ActionScript Class を選んで Finish を押します。すると下の図のような画面が表示されるので Project が MyBrowser になっていることを確かめて、Name のフィールドに PreviousLocations と入力します。今回は Package 等他のフィールドは指定せずにおきます。

この状態で Finish を押すと、PreviousLocations.as というファイルが作成されて同時に AS エディタが開かれます。エディタ内には PreviousLocations のクラス定義の枠だけが作成された状態になります。
これで準備ができたので、このクラス定義の中に MyBrowser.mxml 内のスクリプトから履歴管理に関連した箇所を移動させてきます。
まず、2つの変数定義はどちらもそのまま移動してしまってよさそうです。
private var history:Array = new Array(); private var isPop:int = 0;
isBack は isPop に(新しいメソッド名にあわせて)変えてみました。
次は popLocation() を定義してみます。MyBrowser.mxml の back() がほぼそのまま使えそうです。
public function popLocation():String {
var prevLocation:String = null;
if (history.length > 1) {
history.pop();
prevLocation = history[history.length - 1];
isPop++;
}
return prevLocation;
}
popLocation() の戻り値は、履歴内に戻る先が存在すればその URL、存在しなければ null を返すようにしました。
さらに pushLocation() も定義してみます。こっちは onDomInitialize() からのコードが使えそうです。
public function pushLocation(location:String):void {
if (isPop > 0) {
isPop--;
} else {
history.push(location);
}
}
これは簡単でしたね。そのまま移すだけでした。
さて、これで予定していたメソッドが定義できたので、あとは PreviousLocations クラスに合わせて MyBrowser.mxl 側を直せばよさそうです。が、MyBrowser.mxml をよくみると back() と onDomInitialize() 両関数とも ”戻る” ボタンの状態を設定するために履歴の状況チェックを行っています。
...とすると、PreviousLocations クラスは履歴の状態を公開する手段を何かしら提供する必要がありそうです。
ここではとりあえず下のメソッドを足すことにしてみようと思います。
public function isPopEnabled():Boolean {
return history.length > 1;
}
以上で、履歴管理のクラスは使えそうな感じになりました。
ActionScript コンポーネントの利用
さて、今度は MyBrowser.mxml ファイルを変更していきましょう。
最初に、新しく定義した PreviousLocations クラスのインスタンスを宣言します。
インスタンスは ApolloApplication タグの子タグとして宣言したいと思います。なので、Style タグの次辺りの適当な行で <local と入力します。するとコードヒントに PreviousLocations が出てきます(と思います)のでそれを選択します。id 属性を指定してタグを閉じるとインスタンス宣言の完了です。
<local:PreviousLocations id="prevLocations"/>
このタグを追加してから MyBrowser.mxml の2行目にある ApolloAppication タグを見ると xmlns:local="*" が自動的に追加されているのが分かると思います。今回のようにとりあえずパッケージを指定せず作ったクラスを使うときには便利な機能です。
あとは、back() と onDomInitialize() の修正ですね。
まず back() はこんな感じに。
private function back():void {
var prevURL:String = prevLocations.popLocation();
if (prevURL != null) {
setLocation(prevURL);
backBtn.enabled = prevLocations.isPopEnabled();
}
}
onDomInitialize() はこんなで。
private function onDomInitialize(e:Event):void {
prevLocations.pushLocation(html.location);
inputTF.text = html.location;
backBtn.enabled = prevLocations.isPopEnabled();
}
以上で変更はおしまいです。
ちょっと長くなってしまったので、ここまでに出来上がったコードをまとめておきます。まず、PreviousLocations.as ファイルを。
package
{
public class PreviousLocations
{
private var history:Array = new Array();
private var isPop:int = 0;
public function isPopEnabled():Boolean {
return history.length > 1;
}
public function popLocation():String {
var prevLocation:String = null;
if (history.length > 1) {
history.pop();
prevLocation = history[history.length - 1];
isPop++;
}
return prevLocation;
}
public function pushLocation(location:String):void {
if (isPop > 0) {
isPop--;
} else {
history.push(location);
}
}
}
}
少しスリムになった MyBrowser.mxml です。
<?xml version="1.0" encoding="utf-8"?>
<mx:ApolloApplication xmlns:mx="http://www.adobe.com/2006/mxml" xmlns:local="*">
<mx:Script>
<![CDATA[
private function back():void {
var prevURL:String = prevLocations.popLocation();
if (prevURL != null) {
setLocation(prevURL);
backBtn.enabled = prevLocations.isPopEnabled();
}
}
private function setLocation(location:String):void {
html.location = location;
}
private function onLocationChange(e:Event):void {
html.alpha=0
}
private function onDomInitialize(e:Event):void {
prevLocations.pushLocation(html.location);
inputTF.text = html.location;
backBtn.enabled = prevLocations.isPopEnabled();
}
private function onComplete(e:Event):void {
fadeIn.target = html;
fadeIn.play();
}
]]>
</mx:Script>
<mx:Style source="MyBrowser.css"/>
<mx:Fade id="fadeIn" duration="1000" alphaFrom="0.0" alphaTo="1.0"/>
<local:PreviousLocations id="prevLocations"/>
<mx:HBox>
<mx:TextInput id="inputTF" width="225" text="http://" enter="setLocation(inputTF.text)"/>
<mx:Button label="移動" click="setLocation(inputTF.text)"/>
<mx:Button id="backBtn" label="戻る" click="back()" enabled="false"/>
</mx:HBox>
<mx:HTML id="html" width="100%" height="100%"
locationChange="onLocationChange(event)" domInitialize="onDomInitialize(event)" complete="onComplete(event)"/>
</mx:ApolloApplication>

This site is interesting and very informative, nicely interface. Enjoyed browsing through the site.