yuiを使ったFlexアプリを作って、
便利さを体感しよう


特集:デザイナとプログラマを“結”ぶオープンソース(後編)

クラスメソッド株式会社
渡邊 佳一
2008/10/30


ActionクラスからLogicを利用する

 前回、「Logicは外部インターフェイス呼び出しやデータの処理などビジネスロジックを行うレイヤオブジェクトである」と説明しました。本稿では、サーバ側との連携までは紹介しないので、モックデータを内部的に作成します。ExampleLogicを以下のように書き換えます。

ExampleLogic.as
package yui.example.datavisualization.logic {
import org.seasar.akabana.yui.service.event.ResultEvent;
import yui.example.common.data.Report;

public class ExampleLogic {

    public function ExampleLogic() { }

    public function getData(resultHandler:Function,
        faultHandler:Function = null ):void {
        resultHandler(new ResultEvent(false,false,generateData()));
    }

    private function generateData():Array {
        var a:Array = [
            new Report( "Jan", 2000, 200, 450 ),
            new Report( "Feb", 1000, 500, 600 ),
            new Report( "Mar", 1500, 1200, 300 ),
            new Report( "Apr", 1800, 575, 900 ),
            new Report( "May", 2400, 300, 500 )
        ];
        return a;
    }
}}

非同期処理を想定

 このExampleLogicのgetData関数では、非同期処理をして値を取得するときを想定して、resultHandlerとfaultHandlerの関数を渡して処理するようにしています。次に、ExampleLogicをExampleActionから利用する処理を追加します。

ExampleAction.as
package yui.example.datavisualization.action{
import flash.events.MouseEvent;
import org.seasar.akabana.yui.framework.event.FrameworkEvent;
import org.seasar.akabana.yui.logging.Logger;
import yui.example.datavisualization.logic.ExampleLogic;

public class ExampleAction{
    public function ExampleAction() { }

    public var logger:Logger = Logger.getLogger( ExampleAction );

    public var logic:ExampleLogic;

    public function onAssembleCompleteHandler(
        event:FrameworkEvent ):void {
        logger.debug( ">>> call onAssembleCompleteHandler <<<" );
        logic.getData( getData_resultHandler );
    }

    public function printButtonClickHandler(
        event:MouseEvent ):void {
        logger.debug( ">>> call printButtonClickHandler <<<" );
    }

    private function getData_resultHandler(
        event:ResultEvent ):void { }
    }

}}

 ExampleLogic変数のフィールドを定義して、onAssembleCompleteHandler内でその変数を利用して先ほど作成したgetData関数を呼んでいます。ここでは、ExampleLogicをnewしていないことに着目してください。Actionに定義されたLogicの変数はDI(Dependency Injection)の対象となるので、フレームワーク側でインスタンスが生成されます。

 次に、Helperを使ってこのデータをViewに適用する処理と、印刷ボタンをクリックしたときの処理を追加します。

HelperでUIの更新

 HelperはView表示するデータの適用やViewの振る舞いに対する処理を行うレイヤで、唯一Viewの参照を持ちます。以下のようにHelperに処理を追加します。

ExampleHelper.as
package yui.example.datavisualization.helper {
import flash.display.BitmapData;
import flash.display.Sprite;
import flash.printing.PrintJob;
import flash.printing.PrintJobOptions;

import mx.charts.chartClasses.CartesianChart;
import mx.controls.DataGrid;
import mx.core.Application;
import mx.graphics.ImageSnapshot;

import org.seasar.akabana.yui.logging.LogManager;
import org.seasar.akabana.yui.logging.Logger;

import yui.example.datavisualization.view.ExampleView;

public class ExampleHelper {
    public function ExampleHelper(){ }

    public var view:ExampleView;
    private var printJob:PrintJob;

    public function setupView( value:Array ):void {
        view.linechart.dataProvider = value;
        view.datagrid.dataProvider = value;
    }

    public function print():void {
        var chart:CartesianChart = view.linechart;
        var datagrid:DataGrid = view.datagrid;

        if ( printJob == null ) {
            printJob = new PrintJob();

            var chartBD:BitmapData = ImageSnapshot.
                captureBitmapData(chart,null,null,null,null,true);

            var datagridBD:BitmapData = ImageSnapshot.
                captureBitmapData(datagrid,null,null,null,null,true);
            if ( printJob.start()) {
                var chartsprite:Sprite = new Sprite();
                drawBitmapData( chartsprite, chartBD );

                chartsprite.scaleX = chartsprite.scaleY
                    = printJob.pageWidth / chartsprite.width;

                var datagridsprite:Sprite = new Sprite();
                datagridsprite.y = chartsprite.height;
                drawBitmapData( datagridsprite, datagridBD );

                datagridsprite.scaleX = datagridsprite.scaleY
                    = printJob.pageWidth / datagridsprite.width;

                var sprite:Sprite = new Sprite();
                sprite.visible = false;
                sprite.graphics.clear();
                sprite.graphics.beginFill( 0xFFFFFF );
                sprite.graphics.drawRect(0,0,printJob.pageWidth,                     printJob.pageHeight);
                sprite.graphics.endFill();

                sprite.addChild( chartsprite );
                sprite.addChild( datagridsprite );

                Application.application.stage.addChild( sprite );

                printJob.addPage(sprite,null,
                    new PrintJobOptions(true));
                printJob.send();

                Application.application.stage.removeChild( sprite );
            }
            printJob = null;
        }
    }

    private function drawBitmapData(sprite:Sprite,
        bd:BitmapData ):void {
        if ( sprite != null && bd != null) {
            sprite.graphics.beginBitmapFill( bd,null,false,true);
            sprite.graphics.drawRect(0,0,bd.width,bd.height);
            sprite.graphics.endFill();
        }
    }

}}

 ExampleHelperに、setupView関数とprint関数を追加しました。print関数について、Flexにおける一般的なプリントの処理の記述なので、ここで詳細な説明はしません。

 ただ、どちらもExampleViewのコンポーネントの参照を取得して処理を行っていることに注目してください。Viewはステートフルなオブジェクトなので、Helperに定義されたViewの変数はシングルトンである必要があります。ここでHelperに渡されたViewのインスタンスはnewされるのではなく、フレームワークによって参照が管理されているのです。

ActionからHelperを呼び出す

 では最後に、ActionからHelperを呼び出す処理を追加します。

ExampleAction.as
package yui.example.datavisualization.action {
import flash.events.MouseEvent;
import org.seasar.akabana.yui.framework.event.FrameworkEvent;
import org.seasar.akabana.yui.logging.Logger;
import yui.example.datavisualization.logic.ExampleLogic;

public class ExampleAction {
    public function ExampleAction() { }

    public var logger:Logger = Logger.getLogger( ExampleAction );

    public var helper:ExampleHelper;

    public var logic:ExampleLogic;

    public function onAssembleCompleteHandler(
        event:FrameworkEvent ):void {
        logger.debug( ">>> call onAssembleCompleteHandler <<<" );
        logic.getData( getData_resultHandler );
    }

    public function printButtonClickHandler(
        event:MouseEvent ):void {
        logger.debug( ">>> call printButtonClickHandler <<<" );
        helper.print();
    }

    private function getData_resultHandler(
        event:ResultEvent ):void {
        helper.setupView( event.result as Array );
    }
}}

 printButtonClickHandler処理にExamplerHelperのprint関数を、getData_resultHandlerにExamplerHelperのsetupView関数をそれぞれ呼び出すようにしました。

 これで実装は完了です。実際にアプリケーションを実行してみてください。Chartによるデータ編集、DataGridによるデータ編集、画面の印刷機能の3つが使えると思います。

人がお互い助け合うように

 yuiを使ったFlexアプリケーションの開発はいかがでしたか? 最初は規約を覚えるのに多少学習コストが掛かりますが、これもCoC(Convention over Configuration)の特徴です。一度覚えてしまえば、煩わしい設定ファイルを記述することなく、スムーズに開発ができます。CoCを採用したフレームワークを使ったことがある方なら分かると思います。JavaなどではSeasar 2などがその典型でしょう。

 これからも技術の進歩によって、RIA開発はより複雑で難しくなっていくかもしれません。一方で、yuiのように開発者やデザイナを幸せにするフレームワークや環境なども整備されてくるとも思います。本特集は「デザイナとプログラマの協業」をテーマにしましたが、人が介在する以上、「開発者がお互い助け合う」ということは、これからの開発でも、とても大切なことなのかもしれません。

 今回使ったFlexアプリケーションの完成品のソースは、こちらからダウンロードできます。

@IT関連記事


WebとUIをつなぐトリックスター
Webサイト制作の要となるエンジニアとデザイナのチームワーク。異なる者同士をつなぐトリックスターからヒントを探る
デザインハック」コーナー
業務用RIAの本命!? Flex+Java開発入門
本連載では、サーバサイドとして「Java」、リッチなクライアントサイドとしてJavaと相性の良い「Flex」を用いたRIA開発の基礎を解説します。EclipseベースのIDEである「Flex Builder」を使って、「Tomcat」で動くeラーニングのRIAが完成するまでお届けする予定です
Flashの基礎を無料で習得!
ActionScript入門

ActionScriptを知っていますか? Flash技術の要となる言語で無料で簡単にFlashアプリケーションを作れます。そのActionScriptについて初心者のために一から丁寧に解説していきます
作って学ぶAIRウィジェットの基礎→応用
最近よく聞くAdobe AIRって何だっけ? ウィジェットを簡単に作れるらしいけど…… と曖昧な知識のあなたに贈る超入門連載。楽しいサンプルを作って基礎から応用まで学ぼう
Flex/AIRの開発環境
Flex Builder 3を使ってみよう

現場で使えるFlex実践テクニック(特別編) 今秋に機能確定版がリリース予定のFlex Builder 3。EclipseベースのFlex/AIR開発環境のインストール方法と新機能を紹介
リッチクライアント & 帳票」フ ォーラム 2007/9/6

プロフィール:渡邊 佳一(わたなべ けいいち))
クラスメソッド株式会社 情報システム部門 ITアーキテクト
Adobe Certified Professional Flex 2.0 Developer認定技術者

Flex技術コンサルティングやFlex技術トレーニングを主な業務としている元Javaエンジニア。名前だけだが、Akabanaプロジェクトのコミッターとしての顔を持つ。たまにFxUGなどのコミュニティに顔を出したり出さなかったり。とある事情で会社のHPには載っていない。

1-2-3-4  

 INDEX
特集:デザイナとプログラマを“結”ぶオープンソース(後編) 
yuiを使ったFlexアプリを作って、便利さを体感しよう
  Page1
yuiの便利さは体感しないと分からない!
yuiを使ってデザイナと協業するための環境作り
yuiを利用するまえに
  Page2
まずは、デザイナが画面を作成
命名規則を利用したAction・Helper・Logicの作成
  Page3
自動イベントハンドリング機能の利用
ロギングAPIも使ってみよう
  Page4
ActionクラスからLogicを利用する
HelperでUIの更新
人がお互い助け合うように




HTML5 + UX フォーラム 新着記事
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

HTML5+UX 記事ランキング

本日 月間