SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

特集記事

Flex 2でアウトラインエディタを製作してみる

WindowsアプリをWebアプリとしてリメイク


  • X ポスト
  • このエントリーをはてなブックマークに追加

Treeアイテムの編集

 次に、アウトラインエディタの処理で重要な、アイテムの編集処理について見ていきましょう。ドラッグ&ドロップによるアイテムの移動は、先ほど見たようにTreeのdragEnableddropEnableddragMoveEnabledをtrueにするだけで実現できます。

 そして、アイテムの追加・削除などは、dataProviderに指定したXMLを変更することで対応できます。ここで私もしばらく悩んだのが、アイテムの削除でした。XMLクラスには、アイテムを削除するようなメソッドが用意されていません。それではどうするのかと言うと、delete演算子で要素を削除します。

 ただし、delete演算子は、動的なプロパティのみ削除することができるので、Treeコントロール(index_tree)の選択されたアイテムを削除しようとしたとき、次のように書くとエラーになってしまいます。

Treeの選択されたアイテムを削除(間違った例)
delete index_tree.selectedItem;

 そこで、一度、選択されたアイテムの親を取得し、親の子要素を削除するという処理を行います。

Treeの選択されたアイテムを削除(正しい例)
private function removeCard():void {
    var card:XML = index_tree.selectedItem as XML;
    if (card == null) return;
    var parent:XML = card.parent(); // 親を取得
    if (parent == null) { // ----(*1) 親がない時
        var ci:int = index_data.getItemIndex(card);
        index_data.removeItemAt(ci);
        index_tree.selectedIndex =
            index_data.source.children().length();
    }
    else {
        delete parent.children()[card.childIndex()];
    }
    index_data.refresh();
}

 ここで問題になるのが、親が存在しない場合、つまりXMLのトップレベルのノードだった場合の対処です。プログラム中の(*1)からの部分ですが、トップレベルの場合には、これを削除するremoveItemAtメソッドが用意されています。子要素について、removeItemAtメソッドを利用することはできません。トップレベルか否かによって削除の方法が変わってくるので注意が必要です。

ダイアログのポップアップ

 それから、アウトラインエディタのファイルメニューにある[開く]や[保存]のメニューをクリックすると、ファイル選択ダイアログが表示されるようになっています。これは、PopUpManagerを使うと簡単に実現できます。

 ウィンドウのポップアップを行う手順は、次のようになります。

  1. Flex Builderのメニューから[ファイル]-[新規]-[MXMLコンポーネント]で新規コンポーネントを作る
  2. コンポーネントのベースをTitleWindowに設定して、[終了]をクリック
  3. ウィンドウのデザインを作る
  4. PopUpManager.createPopUp()メソッドでウィンドウをポップアップする

 アウトラインエディタの[出力]メニューをクリックすると、TextAreaを貼り付けただけの簡単なダイアログが表示されますが、これは次のように定義されています。

出力用ダイアログの定義
<?xml version="1.0" encoding="utf-8"?>
<mx:TitleWindow xmlns:mx="http://www.adobe.com/2006/mxml"
layout="absolute" width="450" height="360" title="出力">
<mx:VBox width="100%" height="100%"> <mx:TextArea id="out_txt" width="100%" height="100%"/> <mx:HBox width="100%" horizontalAlign="right"
paddingBottom="4" paddingLeft="4"
paddingRight="4" paddingTop="0">
<mx:Button label="コピー" click="copyText()"/> <mx:Button label="閉じる"
click="PopUpManager.removePopUp(this);"/>
</mx:HBox> </mx:VBox> <mx:Script> <![CDATA[ import mx.managers.PopUpManager; private function copyText():void { // select all out_txt.setFocus(); out_txt.setSelection(0, out_txt.text.length); // copy System.setClipboard(out_txt.text); } ]]> </mx:Script> </mx:TitleWindow>

 このダイアログをモーダルで表示するには、次のように記述します。

出力ダイアログを表示している部分
var frm:ExportDialog = PopUpManager.createPopUp(
    this, ExportDialog, true) as ExportDialog;
PopUpManager.centerPopUp(frm);
frm.out_txt.text = "表示する内容";

ローカル共有オブジェクトへのデータ保存

 このアウトラインエディタでは、編集したファイルの内容を、Flash Playerのローカル共有オブジェクト(SharedObject)に保存するようにしています。これは、ブラウザのクッキーと似た機能なのですが、クッキーには、保存容量の制限があるのに対して、SharedObjectが提供する共有オブジェクトは、ユーザーがアプリケーションごとに任意の保存可能容量を指定することができるようになっています。

 共有オブジェクトには、単純な形式のオブジェクトをそのまま保存することができます。以下のプログラムは、ローカル共有オブジェクトにアウトラインエディタのデータを読み書きするクラスSOFilesからの抜粋です。

データの保存を行うクラス
public class SOFiles
{
    private static var _instance:SOFiles = null;
    private var files_so:SharedObject;
    public function SOFiles(seed:Object) {
        if (seed == null || seed.getInstance == undefined) {
            throw Error("Please use getInstance().");
        }
        files_so = SharedObject.getLocal("SOFiles"); // --------- (*1)
    }
    public static function save(item:SOFileItem):void { // ------ (*2)
        var files_so:SharedObject = SOFiles.getInstance().files_so;
        if (files_so.data.files == undefined) {
            files_so.data.files = new Object();
        }
        files_so.data.files[item.filename] = item;
        files_so.data.lastfile = item.filename;
        files_so.flush();
    }

 クラスのコンストラクタで、ローカル共有オブジェクトを取得しています(*1)。そして、このオブジェクトにデータを書き込むには、dataプロパティにオブジェクトを代入するだけです。

 SOFileItemは、アウトラインエディタのドキュメントの情報を定義したクラスですが、単純なオブジェクトなら、特別なシリアライズ処理をすることなくデータを保存できるようになっています。

 しかし、単純なオブジェクトというのが落とし穴で、オブジェクトのプロパティが別のオブジェクトへの参照だったりすると、うまく保存できません。また、ユーザーが定義したデータを保存した場合に、同じ型での読み込みがうまくいかず、次のようにオブジェクトのプロパティを列挙して、代入する必要がありました。

データの読み込み
public static function load(filename:String):SOFileItem {
    var files_so:SharedObject = SOFiles.getInstance().files_so;
    if (files_so.data.files == undefined) return null;
    files_so.data.lastfile = filename;
    // データの読み込み
    var o:Object = files_so.data.files[filename];
    // ユーザーの定義したクラスのオブジェクトに値を再設定する
    var res:SOFileItem = new SOFileItem();
    for each (var key:String in ['filename','update_date','data']) {
        res[key] = o[key];
    }
    return res;
}

まとめ

 本稿では、Flexを利用して、アウトラインエディタを製作する様子を紹介しました。Flexに用意されている高度なコンポーネントを利用することで、Windowsアプリケーションのような複雑なアプリケーションが手軽に作成できることをお分かりいただけたかと思います。

 なお、このアウトラインエディタを友人に見せたら、「せっかくWebブラウザで動くんだから、ログインしてユーザーごとにサーバーにデータを保存するようにして欲しい」などなど、いろいろな要望が寄せられました。ゆっくりバージョンアップさせていこうと考えています。

「FlexではじめるRIA開発」特集、絶賛公開中!

この記事は参考になりましたか?

  • X ポスト
  • このエントリーをはてなブックマークに追加
特集記事連載記事一覧

もっと読む

この記事の著者

クジラ飛行机(クジラヒコウヅクエ)

ソフト企画「くじらはんど」にて、多数のフリーソフトを公開しています。日本語プログラミング言語「なでしこ」、テキスト音楽「サクラ」、日本語Wiki記法が特徴の「KonaWiki」などを公開しています。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

  • X ポスト
  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/1764 2009/10/20 17:03

おすすめ

アクセスランキング

アクセスランキング

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング