前のページ次のページ上に戻るホーム SophiaFramework UNIVERSE 5.3

9.9. ルート(基礎編)

ルート(SFZRoot)は、 ルートレスポンダ用に設計されたレスポンダです。

レスポンダツリーにイベントを配信したり、 レスポンダツリーを描画するには、そのルートレスポンダに初期化された配信エンジンSFYDistributer)と描画エンジンSFYRenderer)を関連付ける必要があります。

SFYApplication クラスは、内部にデフォルトでルート(SFZRoot)を保持します。

SFYApplication::SFYApplication コンストラクタの処理により、 このルートには、初期化された配信エンジンと描画エンジンが関連付けられています。 SFY アプリの開発では、通常、 このルートを GUI として使用するレスポンダツリーのルートレスポンダとして使用します。

[Note] 注意

1 つのアプリケーションクラスが複数個のルートを保持することも可能ですが、 通常、SFYApplication クラスが内部で保持するデフォルトのルートだけで十分です。

デフォルトのルートを使用する場合は、 配信エンジンと描画エンジンの初期化やルートレスポンダへの関連付けは不要になります。

ルートに対して、 SFYResponder::SetPropertyTransparent(true) を呼び出してもルートは非透過のままです。

表 9.7. 具象ルートの種類

クラス名 解説
SFZRoot ウィンドウ、ダイアログやメニューを配置する汎用ルートです。
[Important] 重要

すべての具象ルートにおいて、 SFYResponder::SetDistributer 関数、 SFYResponder::SetRenderer 関数、 SFYResponder::SetState 関数、 SFYResponder::SetRealBound 関数の呼び出しは必須です。

その他の関数の呼び出しは省略可能です。

9.9.1. ウィンドウ、ダイアログやメニューを配置する汎用ルート[SFZRoot]

SFZRoot は、 ウィンドウダイアログメニューを配置するための汎用的なルートとして機能します。

SFY アプリの開発では、 GUI として使用するレスポンダツリールートレスポンダとして SFYApplication クラスが内部で保持する、 デフォルトのルート(SFZRoot)を利用するので、 新たに別のルートを作成する必要はありません。

[Note] 注意

SFC アプリの開発で SFY レスポンダを利用する場合や、 2 つ以上のレスポンダツリーを使用する場合は、 ルートを作成する必要がありますが、このようなケースはほとんどありません。

図 9.29. 動作例

動作例

以下は、 SFY レスポンダシステムを利用する SFC アプリのアプリケーションクラスの実装コードです (SFYApplication クラスの実装は、下記とほぼ同等の内容です)。

[Note] 注意

SFYApplication クラスには、 サスペンド時に描画エンジンが内部で保持しているデバイス画面保存用ビットマップを解放するオプション機能があります。 以下の実装では、簡略化のため、この機能の実装が省略されています。

詳細は、SFYApplication::HandleEvent 関数の内部実装を参照してください。

例 9.48. 宣言

SFMTYPEDEFCLASS(USRApplication)
class USRApplication: public SFCApplication {
    SFMSEALCOPY(USRApplication)
private:
    SFZRootSmp       _root;         // ルート
    SFYDistributer   _distributer;  // 配信エンジン
    SFYRenderer      _renderer;     // 描画エンジン 
    SFXBaseEditorPtr _editor;       // テキスト入力コントロールエディタ

    // ...(省略)...

private:
    explicit USRApplication(Void) static_throws;    
    virtual ~USRApplication(Void);
    virtual Bool HandleEvent(SFXEventConstRef event);
    virtual Bool HandleRender(SFXEventConstRef event);
    SFCError Make(Void);
    Bool Do(SFXEventConstRef event);
    Void Dispose(Void);
};

例 9.49. 実装 1

SFCError USRApplication::Make(Void)
{
    SFCError error(SFERR_NO_ERROR);

    // 初期化処理

    // テキスト入力コントロールエディタを作成する
    if ((_editor = ::new SFXEditor) != null) {

        // 配信エンジンを初期化する
        error = _distributer.Initialize();
        if (error == SFERR_NO_ERROR) {

            // 描画エンジンを初期化する
            // ※デバイス画面領域(携帯電話の画面領域)がレスポンダ空間として設定される
            error = _renderer.Initialize();
            if (error == SFERR_NO_ERROR) {

                // ルートを作成する
                if ((_root = SFZRoot::NewInstance(&error)) != null) {

                    // ルートに配信エンジンを設定する
                    _root->SetDistributer(&_distributer);

                    // ルートに描画エンジンを設定する
                    _root->SetRenderer(&_renderer);

                    // ルートの実領域を設定する
                    // ※1. 親レスポンダが存在しないルートはレスポンダ空間内に実領域を設定する
                    // ※2. _root->GetSuitableBound() はレスポンダ空間(=デバイス画面領域)を返す
                    // ※3. ルートの実領域はデバイス画面領域に設定される
                    _root->SetRealBound(_root->GetSuitableBound());

                    // ルートの状態を「可視+活性+操作可能+フォーカス」にまとめて設定する
                    _root->SetState(true, true, true, true);
                }
            }
        }
    } else {

        error = SFERR_NO_MEMORY;
    }

    return error;
}

Bool USRApplication::Do(SFXEventConstRef event)
{
    SFCError  error;
    Bool      result(false);

    // 配信エンジンを起動してイベントを配信する
    // ※ イベントは最初にルートに関連付けられた SFYDistributer インスタンスに配信される
    //    その後、トレーサの配信規則に基づいてルート以下のレスポンダツリーに配信される
    if ((error = _root->Distribute(event, &result)) == SFERR_NO_ERROR) {
        // (_root はルート、result 引数にはイベントの処理結果が格納される)

        if (event.GetType() != SFEVT_APP_STOP & event.GetType() != SFEVT_APP_SUSPEND)) {  
            // 再描画が必要な場合

            if (IsRenderable()) {  // 優先的イベントハンドラが登録されていない場合

                // 描画エンジンを起動してルート以下のレスポンダツリーを再描画する
                error = _root->Render();
            }
        }
    }
    if (error != SFERR_NO_ERROR) {
        // 配信エンジンや描画エンジンの起動時にメモリ不足などの致命的エラーが発生した場合

        if (HandleError(event, error)) {

            result = true;
        }
    }
    return result; // イベントを処理したときは true を返し, そうでないときは false を返す
}

Void USRApplication::Dispose(Void)
{
    // 終了処理(必ず下記の順序で行う)

    // テキスト入力コントロールエディタを破棄する
    ::delete _editor;

    // レスポンダツリーを解放する
    _root.Release();

    // 描画エンジンを終了する
    _renderer.Terminate();

    // 配信エンジンを終了する
    _distributer.Terminate();

    return;
}
[Note] レスポンダ空間

レスポンダ空間とは、 描画エンジンに関連付けられた、 レスポンダツリーを描画する領域のことです。

レスポンダ空間は、 SFYRenderer::Initialize 関数を呼び出したとき、 自動的にデバイス画面領域(携帯電話の画面領域)に設定され、この領域は変更できません。

上記コードの USRApplication::Make 関数、USRApplication::Do 関数、USRApplication::Dispose 関数は、 以下のようにコンストラクタ、イベントハンドラ、デストラクタからそれぞれ呼び出されます。

例 9.50. 実装 2

// コンストラクタ
USRApplication::USRApplication(Void)
{
    if (static_try()) {
 
        static_throw(Make());
 
        // その他の初期化処理を記述する
 
    }
}

// イベントハンドラ
Bool USRApplication::HandleEvent(SFXEventConstRef event)
{
    SFCError    error;
    Bool        result(false);

    result = Do(event);
 
    // その他の処理を記述する
 
    return result;
}

// 全画面再描画ハンドラ
Bool USRApplication::HandleEvent(SFXEventConstRef event)
{
    // ここに全画面(デバイス画面とルート以下のレスポンダツリー)の再描画を記述する
    SFCError  error;
    Bool      result(false);

    if (SFCApplication::HandleRender(event)) { // デバイス画面を再描画する

        // ルート以下のレスポンダツリーを再描画する
        // ※1. 可能であれば、デバイス画面保存用ビットマップを利用して高速に再描画行う
        // ※2. SFEVT_APP_START 受信時などデバイス画面保存用ビットマップが利用不可の場合は引数に true を指定して Render 関数を呼び出す(強制再描画を行う)
        error = _root->Render((event.GetType() == SFEVT_APP_START) || (_root->Recover() != SFERR_NO_ERROR));

        if (error == SFERR_NO_ERROR) {

            result = true;
        }
        else {
            // 描画エンジンの起動時にメモリ不足などの致命的エラーが発生した場合、HandleError() を呼び出す
            HandleError(event, error);
        }
    }
    return result;
}

// デストラクタ
USRApplication::~USRApplication(Void)
{
    Dispose();
 
    // その他の終了処理を記述する
}