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

9.2. レスポンダシステムの構成要素

レスポンダシステムには、 レスポンダツリー、ルートレスポンダ、親子・姉妹関係、レスポンダ空間、領域、 状態、イベント、イベントループ、トレーサ、ハンドラなどの構成要素があります。

この節では、これらのレスポンダシステムの構成要素について解説します。

9.2.1. レスポンダツリー

レスポンダツリーとは、 複数個のレスポンダから構成される木構造のことです。 木構造の頂点に位置するレスポンダはルートレスポンダと呼ばれます。

レスポンダツリーはレスポンダを管理するため利用され、 以下の順序関係でレスポンダ空間に描画されます。

  1. 子レスポンダ親レスポンダよりも前面にあります。
  2. 姉妹レスポンダでは、姉レスポンダは妹レスポンダよりも前面にあります。
  3. 姉レスポンダは妹レスポンダの子レスポンダよりも前面にあります。

[Tip] ToFront 関数

ボタンやラベルなどのコントロールを子レスポンダとして持つウィンドウの SFYResponder::ToFront 関数を呼び出すと、 ウィンドウの子レスポンダも一緒に最前面に移動します。

図 9.3. レスポンダツリーの構造


レスポンダツリーの構造

SFZWindow(参照:右側の不完全なレスポンダツリー)は、 SFZRoot(参照:左側の完全なレスポンダツリー)を親レスポンダに設定するまでの間は親レスポンダが存在しないのでルートレスポンダです。

例 9.4. レスポンダツリーの作成

SFCError USRApplication::MakeTree(Void)
{
    SFZRootSmp root;
    SFZDialogSmp dialog;
    SFZTextButtonControlSmp button;
    SFZWindowSmp window;
    SFZTextLabelControlSmp label;
    SFCError error(SFERR_NO_ERROR);

    // SFYApplication クラスが内部に保持するルートを取得する
    if ((root = GetThis() != null) { 

        // ダイアログを生成する
        if ((dialog = SFZDialog::NewInstance(&error)) != null) {

            // ダイアログの親レスポンダをルートに設定する
            if ((error = dialog->SetParent(root)) == SFERR_NO_ERROR) {

                // テキストボタンコントロールを生成する
                if ((button = SFZTextButtonControl::NewInstance(&error)) != null) {

                    // テキストボタンコントロールの親レスポンダをダイアログに設定する
                    if ((error = button->SetParent(dialog)) == SFERR_NO_ERROR) {

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

        if (error == SFERR_NO_ERROR) {

            // ウィンドウを生成する
            if ((window = SFZWindow::NewInstance(&error)) != null) {

                // ウィンドウの親レスポンダをルートに設定する
                if ((error = window->SetParent(root)) == SFERR_NO_ERROR) {

                    // テキストラベルコントロールを生成する
                    if ((label = SFZTextLabelControl::NewInstance(&error)) != null) {

                        // テキストラベルコントロールの親レスポンダをウィンドウに設定する
                        if ((error = label->SetParent(window)) == SFERR_NO_ERROR) {

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

    return error;
}
[Note] 注意

SFYApplication クラスは、 SFYApplication::SFYApplication コンストラクタ内の処理によりルートSFZRoot)を作成し保持しています。

9.2.2. ルートレスポンダ

ルートレスポンダとは、 レスポンダツリーの頂点に位置するレスポンダです。

ルートレスポンダに配信エンジン(SFYDistributer)と描画エンジン(SFYRenderer)を関連付けると、 レスポンダツリー上のレスポンダの有効状態は ON になり、 レスポンダツリーにイベントを配信したり、レスポンダツリーを描画することが可能になります。

図 9.4. ルートレスポンダと配信エンジン・描画エンジンの関係

ルートレスポンダと配信エンジン・描画エンジンの関係
[Note] 注意

一般に、 ルートSFZRoot)をルートレスポンダとして利用します。

ウィンドウやコントロールなどのレスポンダも、 作成してからレスポンダツリーに接続されるまでは親レスポンダが存在しないので形式上はルートレスポンダです。 しかし、一般的にルート以外のレスポンダに配信エンジンと描画エンジンを設定することはありません。

例 9.5. ルートへの配信エンジンと描画エンジンの設定

SFCError USRApplication::MakeRoot(Void)
{
    SFYDistributer _distributer;  // 配信エンジン
    SFYRenderer _renderer;        // 描画エンジン
    SFZRootSmp _root;             // ルート
    SFCError error(SFERR_NO_ERROR);

    // ********************************************************************************
    // 以下の処理は SFYApplication クラスのコンストラクタ内で実装済みです。            
    // 一般のアプリ開発では、実装する必要はありません。                                
    // ********************************************************************************

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

        // 描画エンジンを初期化する
        // ※引数に指定した携帯電話の画面領域がレスポンダ空間となる
        error = _renderer.Initialize(SFXGraphics::GetDeviceRectangle());
        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);
            }
        }
    }

    return error;
}
[Tip] Tip

SFYApplication クラスは、 内部にルートSFZRoot)を保持しています。 SFYApplication::SFYApplication コンストラクタ内で、 このルートに配信エンジン描画エンジンを関連付ける処理を行っています。 SFYApplication クラスを継承するユーザー定義のアプリケーションクラスでは、 上記のコードを実装する必要はありません。

参照: SFZRoot | SFYDistributer | SFYRenderer | SFYResponder::SetDistributer | SFYResponder::SetRenderer

9.2.3. 親レスポンダ

親レスポンダとは、自レスポンダを所有している親となるレスポンダのことです。

ウィンドウ内にボタンコントロールが存在する場合、 ウィンドウはボタンコントロールの親レスポンダです。

GUI コンポーネントとして画面に配置するとき、 親レスポンダは子レスポンダよりも背面に配置されます。

[Tip] Tip

親レスポンダは SFYResponder::SetParent 関数を使用して設定します。

親レスポンダを設定すると、 レスポンダは親レスポンダが所属しているレスポンダツリーに接続されます。

図 9.5. 親レスポンダとの包含関係

親レスポンダとの包含関係

例 9.6. 親レスポンダの設定

SFCError USRResponder::SetButtonParent(Void)
{
    SFZWindowSmp window;
    SFZTextButtonControlSmp button;
    SFCError error(SFERR_NO_ERROR);

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

    // button の親レスポンダを window に設定する
    if ((error = button->SetParent(window)) == SFERR_NO_ERROR) {

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

    return error;
}

例 9.7. 親レスポンダのクリア

SFCError USRResponder::ClearButtonParent(Void)
{
    SFZTextButtonControlSmp button;
    SFCError error(SFERR_NO_ERROR);

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

    // SFYResponderSmp::EmptyInstance() を指定して親レスポンダをクリアする
    if ((error = button->SetParent(SFYResponderSmp::EmptyInstance())) == SFERR_NO_ERROR) {

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

    return error;
}
[Tip] Tip

親レスポンダをクリアするには、レスポンダの SFYResponder::SetParent 関数の引数に SFYResponderSmp::EmptyInstance() を指定します。 この操作によりレスポンダはレスポンダツリーから分離されます。

9.2.4. 子レスポンダ

子レスポンダとは、 自レスポンダが所有している子となるレスポンダのことです。

ウィンドウ内にボタンコントロールが存在する場合、 ボタンコントロールはウィンドウの子レスポンダです。

GUI コンポーネントとして画面に配置するとき、 子レスポンダは親レスポンダよりも前面に配置されます。

図 9.6. 子レスポンダとの包含関係

子レスポンダとの包含関係

例 9.8. 子レスポンダの検索

SFYResponderSmp USRResponder::SearchChild(SInt32 index) const
{
    // 可視の子レスポンダの中で前面から index 番目の子レスポンダを検索する
    // この他にもいくつかの検索方法が利用可能
    return GetChildForward(index, true, false, false, false);
}

参照: SFYResponder::GetChildBack | SFYResponder::GetChildFront | SFYResponder::GetChildBackward | SFYResponder::GetChildForward | SFYResponder::GetChildCount

9.2.5. 姉妹レスポンダ

姉妹レスポンダとは、 自レスポンダと同じ親レスポンダを持つ姉妹となるレスポンダのことです。

GUI コンポーネントとして画面に配置するとき、 姉レスポンダは妹レスポンダよりも前面に配置されます。

図 9.7. 姉妹レスポンダとの包含関係

姉妹レスポンダとの包含関係

例 9.9. 姉妹レスポンダの検索

SFYResponderSmp USRResponder::SearchNextSister(Void) const
{
    SFYResponderSmp parent;
    SFYResponderSmp result;

    // 自レスポンダと同じ親レスポンダを持つすべての姉妹レスポンダの中で
    // 自レスポンダの次の姉妹レスポンダを検索する
    if ((parent = GetParent()) != null) {

        if ((index = GetNthBackward(false, false, false, false)) > 0) {

            result = parent->GetChildBackward(index - 1, false, false, false, false);
        }
    }

    return result;
}

参照: SFYResponder::GetChildBackward | SFYResponder::GetChildBack | SFYResponder::GetNthBackward | SFYResponder::ToNthBackward | SFYResponder::IsNthBackward | SFYResponder::ToBack | SFYResponder::IsBack | SFYResponder::GetChildForward | SFYResponder::GetChildFront | SFYResponder::GetNthForward | SFYResponder::ToNthForward | SFYResponder::IsNthForward | SFYResponder::ToFront | SFYResponder::IsFront

9.2.6. レスポンダ空間

レスポンダ空間とは、 レスポンダツリーを描画するための、 携帯電話の画面左上端を原点とする絶対座標系で表した矩形領域のことです。 デフォルトでは SFXGraphics::GetDeviceRectangle() の戻り値である携帯電話の画面領域に設定されます。

レスポンダ空間は、 描画エンジン(SFYRenderer)を初期化する SFYRenderer::Initialize 関数の引数に指定します。

ルートレスポンダ(ルート) の実領域は、 レスポンダ空間の左上端を原点とする相対座標系の矩形領域として表されます。

[Note] レスポンダ空間の変更

一旦設定すると、それ以降レスポンダ空間の領域は変更できません。

一般的なアプリ開発では、 SFYApplication::SFYApplication コンストラクタによる初期設定 [SFXGraphics::GetDeviceRectangle() の戻り値である携帯電話の画面領域] で十分なので、レスポンダ空間を設定する必要はありません。

[Caution] 注意

レスポンダ空間からはみ出した領域には描画されません。

9.2.7. 実領域

実領域とは、 親レスポンダのローカル領域の左上端を原点とする相対座標系で表された、 レスポンダのクリッピング領域です(ローカル領域に描画されたレスポンダの内容はこの領域でクリッピングされて画面に表示されます)。

[Tip] Tip

実領域は SFYResponder::SetRealBound 関数を使用して設定します。

[Note] 注意

実領域のサイズはグローバル領域のサイズと一致します。

図 9.8. 実領域の位置関係


実領域の位置関係

※実領域は、親レスポンダのローカル領域の左上端を原点とする相対座標系の矩形(SFXRectangle)として表されます。

例 9.10. 最適な領域を取得してから実領域を設定する方法

Void USRResponder::SetButtonBound(Void)
{
    SFZTextButtonControlSmp button;

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

    // テキストボタンコントロールのテキストを設定する
    button->SetText("Text Button");

    // テキストボタンコントロールの最適な領域を取得してから実領域を設定する
    button->SetRealBound(button->GetSuitableBound().SetOrigin(10, 10));

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

    return;
}
[Tip] Tip

SFYResponder::GetSuitableBound 関数を利用すれば、 テキストボタンコントロールに設定されたテキスト、フォントなどの情報から最適な領域を取得できます。

この関数で得られる領域の始点はデフォルトで (0, 0) なので、 必要に応じて SFXRectangle::SetOrigin / SFXRectangle::Offset 関数などを利用して最適な場所に配置します。

[Warning] 実領域の初期値

NewInstance 関数を実行した直後、 実領域は SFXRectangle(0, 0, 0, 0) です。 子レスポンダを配置するには、 SFYResponder::SetRealBound 関数を使用して実領域を設定する必要があります。

[Note] ルートの実領域

SFYApplication クラスが内部に保持するルートSFZRoot)には親レスポンダが存在しません。 ルートの実領域は、 レスポンダ空間の左上端を原点とする相対座標系の矩形領域として表されます。

SFYApplication::SFYApplication コンストラクタ内の処理により、 ルートの実領域はレスポンダ空間と同じ矩形領域(携帯電話の画面領域)に初期設定されます。

[Tip] Tip

通常、ルートの実領域を設定したり変更する必要はありません。

[Caution] 実領域と仮想領域

SFYResponder::SetRealBound 関数を使用して実領域を小さくすると、 仮想領域は実領域よりも大きくなります。

[Tip] Tip

実領域よりも大きな仮想領域を持つ必要のないレスポンダでは、 SFYWidget::HandleBoundReal 関数をオーバーライドして仮想領域を実領域に一致させるとよいでしょう。

SFYControl::HandleBoundReal 関数は仮想領域を実領域に一致させます。

9.2.8. 仮想領域

仮想領域とは、 実領域(レスポンダの可視領域)の左上端を原点とする相対座標系で表したレスポンダの領域のことです。

仮想領域の始点を移動すると、レスポンダの領域はスクロールして可視領域(実領域)上に表示されます。

仮想領域を設定しない場合、レスポンダの領域(仮想領域)は可視領域(実領域)になります。

[Tip] Tip

仮想領域は SFYResponder::SetVirtualBound 関数を使用して設定します。

[Note] 注意

仮想領域のサイズはローカル領域のサイズと一致します。

図 9.9. 仮想領域と実領域の位置関係


仮想領域と実領域の位置関係

※仮想領域は、実領域の左上端を原点とする相対座標系の矩形(SFXRectangle)として表されます。

図 9.10. 実領域と仮想領域の配置関係


実領域と仮想領域の配置関係

※仮想領域は実領域を含む必要があります。

例 9.11. レスポンダ領域をスクロールして表示する方法

Void USRResponder::ScrollVirtualBound(Void)
{
    // 現在の仮想領域を取得し、原点の Y 座標を 10 ピクセル分減算することにより
    // 仮想領域を 10 ピクセル分上にスクロールする
    SetVirtualBound(SFXRectangle(GetVirtualBound()).SubY(10));

    return;
}

9.2.9. ローカル領域

ローカル領域とは、 レスポンダ領域の左上端を原点とする座標系で表したレスポンダの領域のことです。

レスポンダの描画処理は、 描画ハンドラ内で SFYResponder::GetLocalBound 関数の戻り値であるローカル領域に対して行います。

[Tip] Tip

ローカル領域は SFYResponder::GetLocalBound 関数を使用して取得します。

[Note] 注意

ローカル領域のサイズは仮想領域のサイズと一致します。

図 9.11. ローカル領域の位置関係


ローカル領域の位置関係

※ローカル領域は、レスポンダ領域の左上端を原点とする相対座標系の矩形(SFXRectangle)として表されます。

例 9.12. ローカル領域を用いた描画

XANDLER_IMPLEMENT_VOIDRENDER(USRResponder, OnRenderRequest, invoker, reason, graphics)
{
    // ローカル領域全体を白色で塗り潰す
    graphics->FillRectangle(GetLocalBound(), SFXRGBColor(0xFF, 0xFF, 0xFF, 0x00));

    return;
}
[Warning] ローカル領域の初期値

NewInstance 関数を実行した直後、レスポンダのローカル領域は SFXRectangle(0, 0, 0, 0) です。 子レスポンダを配置するには、 SFYResponder::SetRealBound 関数を使用してレスポンダの実領域を設定する必要があります。

9.2.10. グローバル領域

グローバル領域とは、 携帯電話の画面左上端を原点とする絶対座標系で表したレスポンダの可視領域のことです。

[Tip] Tip

グローバル領域は SFYResponder::GetGlobalBound 関数を使用して取得します。

[Note] 注意

グローバル領域は、 標準 BREW インターフェースにレスポンダの可視領域を絶対座標系で表して渡す場合に利用します。

グローバル領域のサイズは実領域のサイズと一致します。

図 9.12. グローバル領域の位置関係


グローバル領域の位置関係

※グローバル領域は、画面の左上端を原点とする絶対座標系の矩形(SFXRectangle)として表されます。

9.2.11. 可視領域

可視領域とは、 実際に利用者から携帯電話の画面上に見える、 レスポンダの領域のことです (一般的には、レスポンダの実領域またはその部分領域になります)。

レスポンダが不可視状態である場合、 可視領域は空の領域となります(レスポンダは可視領域を持ちません)。

レスポンダの実領域が親レスポンダの実領域やレスポンダ空間からはみ出る場合や、 レスポンダの実領域内の部分的な領域が他のレスポンダの隠れる場合は、 可視領域は実領域の部分的な領域となります。

[Note] 注意

SFYResponder::Invalidate 関数を呼び出して再描画領域を登録しても、 その領域がレスポンダの可視領域と共通部分を持たない限り、 描画ハンドラは起動されません。

9.2.12. 再描画領域

再描画領域とは、 SFYResponder::Invalidate 関数で登録する、 レスポンダのローカル領域内の矩形領域 (ローカル領域の座標系で表します)のことです。

SFYResponder::Render 関数により 描画エンジンを起動したとき、 以下のように可視領域を持つレスポンダの描画ハンドラだけが起動の対象となります。

引数に false(デフォルト値)を指定して Render 関数を呼び出した場合は、 可視領域が SFYResponder::Invalidate 関数で登録される再描画領域と共通部分を持つ場合に限り、 描画ハンドラが起動されます。

true を指定した場合は、 再描画領域の登録に関係なく、可視領域を持つすべてのレスポンダの描画ハンドラが起動されます。

[Caution] 注意

SFYResponder::Invalidate 関数で再描画領域を登録しても、 その領域がレスポンダの可視領域と共通部分を持たない限り、 描画ハンドラは起動されません。

[Note] 注意

詳細は、描画処理を参照してください。

9.2.13. 属性

レスポンダには背景が透過であるかどうかを表す透過属性があります。

透過属性のデフォルト値は false(非透過) ですが、 一部のレスポンダ(ラベルやラジオボタン、チェックボックスなど)では true(透過)にデフォルト設定されています。

属性が非透過である場合、 レスポンダの背景は SFYWidget::SetBackgroundColor 関数で設定された背景色(デフォルト: 白色)で塗り潰されます。

[Tip] Tip

透過属性は SFYResponder::SetProperty / SFYResponder::SetPropertyTransparent 関数を使用して設定します。

図 9.13. 透過属性の例: テキストラベルコントロール[SFZSingleTextLabelControl]とチェックボックスコントロール[SFZCheckboxControl]


透過属性の例: テキストラベルコントロール[SFZSingleTextLabelControl]とチェックボックスコントロール[SFZCheckboxControl]

テキストラベルコントロール[SFZSingleTextLabelControl]やチェックボックスコントロール[SFZCheckboxControl]では、 透過属性は true に設定されているので、左図のようにこれらのレスポンダの背景は塗り潰されません。

透過属性を false に設定すると、 背景は右図のように白色(デフォルト設定の場合)で塗り潰されます。

例 9.13. 透過属性の設定

Void USRResponder::SetTransparent(Void)
{

    // USRResponder の透過属性を true に設定する
    SetPropertyTransparent(true);

    return;
}

参照: SFYResponder::SetProperty | SFYResponder::SetPropertyTransparent | SFYWidget::SetBackgroundColor

9.2.14. 状態

レスポンダには優先順位付けされた 5 つの状態があります。

  1. 有効状態
  2. 可視状態
  3. 活性状態
  4. 操作可能状態
  5. フォーカス状態
[Note] 注意
有効状態が最も高い優先順位、フォーカス状態が最も低い優先順位を持ちます。

各状態の定義は以下の表の通りです。

表 9.2. レスポンダの状態

優先度 名称 解説
1 有効状態 有効 / 無効

レスポンダがイベントを受信できるかどうかを表します。

レスポンダは、 配信エンジンが接続されたレスポンダツリーに所属するときに限り有効です。

SFYResponder::Terminate 関数を呼び出すと、 レスポンダはレスポンダツリーから切り離され、「無効」の状態になります。

2 可視状態 可視 / 不可視

レスポンダが見えるかどうかを表します。

親レスポンダの実領域の外側にあるレスポンダや姉妹レスポンダに覆い隠されて描画されないレスポンダは、 不可視に設定しておくと描画速度が向上します。

3 活性状態 活性 / 不活性

レスポンダが操作対象になりえるかどうかの外観を表します。

レスポンダは不活性状態にあるとき、 ラベルテキストや枠線の色が薄くなったり、 立体的なレスポンダは平面的なデザインになったりします。

活性状態はレスポンダの外観にだけ効果をもたらします。

4 操作可能状態 操作可能 / 操作不能

レスポンダが操作可能かどうかを表します。

活性状態とは異なり、操作可能でも操作不能でもレスポンダの外観は同じです。

操作不能状態であるとき、 レスポンダはフォーカスされることはありません(操作対象になりません)。

5 フォーカス状態 フォーカス / 非フォーカス

レスポンダが操作対象になっているか(フォーカスされているか)どうかを表します。

フォーカス状態にあるとき、 フォーカス枠が描画されたりします。

フォーカス状態のフラグは、他のすべての状態フラグが true である場合に限り、 true に設定可能です。 また、他の状態のフラグが 1 つでも false に変更されると、 自動的に false に設定されます。

姉妹レスポンダの中では、高々 1 つのレスポンダにしかフォーカス状態フラグを true に設定できません。

操作可能な他の姉妹レスポンダのフォーカス状態フラグを true に設定すると、 レスポンダはフォーカス状態フラグは false に設定されます。

フォーカス状態フラグが true であるレスポンダが破棄されたとき、 フォーカスは操作可能状態にある他の姉妹レスポンダに移動します。 具体的には、背面に操作可能状態にある姉妹レスポンダがある場合は、 1 つだけ背面にある、 フォーカス状態の以外の他のすべての状態フラグが true である姉妹レスポンダのフォーカス状態フラグが true になります。 そのような姉妹レスポンダが存在しない場合は、 1 つだけ前面にある、 フォーカス状態の以外の他のすべての状態フラグが true である姉妹レスポンダのフォーカス状態フラグが true になります。

なお、フォーカス状態フラグが true であるレスポンダのフォーカス状態フラグを false に変更した場合は、 どの姉妹レスポンダにもフォーカスは移動しません。

[Note] レスポンダの初期状態

NewInstance 関数を使用してインスタンスを生成した直後、 レスポンダの状態フラグは以下のように初期化されます。

  1. 有効状態フラグ: true
  2. 可視状態フラグ: false
  3. 活性状態フラグ: false
  4. 操作可能状態フラグ: false
  5. フォーカス状態フラグ: false

[Warning] 注意
  1. SFYResponder::Terminate 関数を呼び出して有効状態フラグが false に設定されたレスポンダに対して SFYResponder::Initialize 関数を呼び出して再初期化してはいけません。
  2. 有効状態フラグの値が false であるレスポンダにイベントを送信してはいけません。
    [Tip]

    デストラクタ内で処理をしているとき、 有効状態フラグの値は false なので自分自身にイベントを送信してはいけません。

図 9.14. 5 つの状態の例: テキストボタンコントロール[SFZTextButtonControl]

5 つの状態の例: テキストボタンコントロール[]
5 つの状態の例: テキストボタンコントロール[SFZTextButtonControl]

テキストボタンコントロール[SFZTextButtonControl]は状態に応じて外観が変化します。

図 9.15. 5 つの状態の例(拡大図): テキストボタンコントロール[SFZTextButtonControl]


5 つの状態の例(拡大図): テキストボタンコントロール[SFZTextButtonControl]

状態に応じて、テキストボタンコントロール[SFZTextButtonControl]を構成する要素の色が変化したり、 表示されたりされなかったりします。

  • 有効: 不可視状態なのでボタンは表示されません。
  • 有効+可視: ボタンは表示されますが、ボタンのベベル領域のライトカラーとダークカラーがベースカラーと同じになり平面的に見えます。また、ラベルと影の色も少し薄く表示されます。
  • 有効+可視+活性: ボタンのベベル領域のライトカラー、ダークカラー、ベースカラーが異なる色で表示され立体的に見えます。ラベルと影の色もはっきりと表示されます。
  • 有効+可視+活性+操作可能: 「有効+可視+活性」状態と外観は同じですが、フォーカス移動が可能です。
  • 有効+可視+活性+操作可能+フォーカス: ボタンのベベル領域の枠の色が強調されると同時にフォーカスの枠がベベル領域の内側に表示されます。
[Note] テキストボタンコントロールの構成要素
  • 影領域(非押下時: 右辺と下辺、押下時: 左辺と上辺)
  • ベベル領域(ライトカラー、ベースカラー、ダークカラーの 3 種類の色で構成される矩形領域)
  • フォーカス状態の時に表示される枠(フォーカス枠)
  • テキストラベル

詳細情報: SFYButtonControl | SFZTextButtonControl | SFXBevelColor

[Note] フォーカス状態フラグについて

SFYResponder::SetState 関数を呼び出す直前、 レスポンダの可視、活性、操作可能、フォーカスのすべての状態のフラグ値が true であったとします (このレスポンダがフォーカスを持っていたとします)。

この場合、 visible、active、または enable 引数のうち 1 つ以上の引数に false を指定して SFYResponder::SetState 関数を呼び出せば、 focus 引数に true を指定していても、 このレスポンダのフォーカス状態フラグの値は強制的に false に設定されます。

そして、もし存在すれば、1 つだけ背面にある操作可能な姉妹レスポンダ (存在しない場合は、1 つだけ前面にある操作可能な姉妹レスポンダ) のフォーカス状態フラグが false から true に変更されます (フォーカスはその姉妹レスポンダに移動します)。

※1. フォーカス状態のフラグ値を true に設定するには、 visible / active / enable / focus のすべての引数に true を指定して SFYResponder::SetState 関数を呼び出す必要があります。 このとき、 フォーカス状態のフラグが true である姉妹レスポンダが存在した場合、 そのフラグは 強制的に false に変更されます (その姉妹レスポンダはフォーカスされない状態になります)。

※2. 操作可能なレスポンダとは、 可視、活性、操作可能の状態フラグの値が true であるレスポンダのことです。

※3. 可視、活性、操作可能の状態フラグは、 SFYResponder::SetState 関数の対応する各引数に指定した値が無条件にそのまま設定されます。

例 9.14. 状態の設定

Void USRResponder::SetState(Void)
{
    // 可視、活性、操作可能、フォーカスの各状態のフラグを true に設定し、
    // このレスポンダのフォーカス状態を ON にする
    SetState(true, true, true, true);
    // ※ 親レスポンダのフォーカス状態は ON であると仮定

    // 可視状態のフラグを false に設定する(このレスポンダを不可視状態 OFF にする)
    SetStateVisible(false);
    // ※ このとき、活性状態と操作可能状態のフラグ値は true のままだが、
    //    フォーカス状態フラグ値は自動的に true から false に変更されることに注意!
    //    そして、もし存在すれば、1 つだけ背面にある操作可能な姉妹レスポンダ(存在しない場合は、1 つだけ前面にある操作可能な姉妹レスポンダ)の
    //    フォーカス状態フラグが false から true に変更される(その姉妹レスポンダにフォーカスが移動する)

    // 可視状態のフラグを true に設定すると、操作可能状態 ON になるが、
    // フォーカス状態フラグ値は false のままなので、フォーカス状態は OFF
    SetStateVisible(true);

    // フォーカス状態を ON にするには、フォーカス状態フラグを true に設定する必要がある
    SetStateFocus(true);

    return;
}

レスポンダが状態フラグに設定されているように実際に振舞う場合、 レスポンダの状態は ON、 そうでない場合は OFF であると呼ぶことにします。

可視、活性、または操作可能の状態フラグが true に設定されていたとしても、 レスポンダはそのように振舞うとは限りません。 しかし、 フォーカスの状態フラグの値は、 フォーカス状態が ON である(フォーカスされている)ときに限り true です。 逆に言えば、 フォーカス状態が OFF である(フォーカスされていない)ときは false です。

[Tip]

可視状態フラグの値が true であったとしても、 レスポンダが描画されなければ、可視状態は OFF です。 逆に、実際に描画されるならば、可視状態は ON です。

レスポンダの状態が ON であるか否かは、 以下のように再帰的に決定できます(3 つの条件がすべて成立すれば、状態は ON です)。

  1. 状態フラグが true に設定されている
  2. (もし存在すれば)1 つ優先順位の高い状態が ON である
  3. (もし存在すれば)親レスポンダの同じ状態が ON である
[Note] 状態の優先順位

有効、可視、活性、操作可能、フォーカスの順で各状態に優先順位が付けれています。

[Tip] Tip

SFYResponder::GetStateVisible / SFYResponder::GetStateActive / SFYResponder::GetStateEnable / SFYResponder::GetStateFocus 関数では、 inherit 引数の指定により、状態のフラグ値、またはON / OFF 値を取得できます。

[Note] 状態の ON / OFF 値
  1. いま画面上にウィンドウが描画されているとすれば、 ウィンドウの可視状態フラグは true、可視状態は ON です。

    ウィンドウ内にボタンも描画されていれば、 ボタンの可視状態フラグも true、可視状態も ON です。 ボタンの可視状態も ON です。

    ここで、 ウィンドウの可視状態フラグを false にすると、 ウィンドウの可視状態は自動的に OFF になり、 ウィンドウは描画されなくなります。

    子であるボタンの可視状態も自動的に OFF になり、 ボタンも描画されなくなります。 このとき、ボタンの可視状態フラグは true のままです。

  2. いま画面上にボタンがフォーカスされているとすれば、 ボタンのフォーカス状態と可視状態は共に ON です。

    フォーカス状態よりも優先順位の高い可視状態フラグを false に設定すると、 フォーカス状態は自動的に OFF になり、 ボタンはフォーカスされなくなります。 このとき、 活性状態と操作可能状態のフラグ値は true のままですが、 フォーカス状態フラグだけは false になる仕様に注意が必要です (再びフォーカス状態を ON にするには、フォーカス状態フラグを true に設定する必要があります)。

[Note] 状態イベントの処理

レスポンダは、状態の ON / OFF が切り替わると、 状態イベントを受信します。

このイベントについて 状態イベント専用ハンドラを登録することが可能です。

参照: SFYResponder::Initialize | SFYResponder::Terminate | SFYResponder::SetState | SFYResponder::SetStateVisible | SFYResponder::SetStateActive | SFYResponder::SetStateEnable | SFYResponder::SetStateFocus

9.2.15. イベント

イベント(SFXEvent)は、 イベントタイプと 2 つのパラメータ(P16 パラメータと P32 パラメータ)から構成されます。

イベントを処理するハンドラは、 SFYResponder::RegisterHandler / SFYDistributer::RegisterHandler 関数を使用してレスポンダ、または ルートSFZRoot)に設定された SFYDistributer インスタンスに登録します。

イベントには、以下の 3 種類があります。

  1. BREW SDK で定義される BREW イベント
  2. SophiaFramework UNIVERSE 独自のレスポンダイベント
  3. 開発者独自のユーザーイベント

BREW イベントのイベントタイプ名は、BREW SDK で定義されるイベントタイプ名の先頭に SF 接頭語が付加された名前になります。

たとえば、SFEVT_KEY イベント(キーイベント[SFEVT_KEY])は BREW イベントです。

一方、レスポンダイベントのイベントタイプ名は、 SFEVT_RESPONDER_ 接頭語が付加された名前になります。

たとえば、SFEVT_RESPONDER_RENDER イベント(描画イベント)は レスポンダイベントです。

また、イベントの配信方法からイベントは配信型イベントと、 コールバック型イベントの 2 種類に分類されます。

配信型イベントは SFYResponder::Distribute 関数を使用してレスポンダに配信します (このとき、トレーサの配信規則が参照されます)。 イベントを受信したレスポンダは対応するハンドラを呼び出します。 BREW イベントは配信型イベントです。

コールバック型イベントは SFYResponder::InvokeForward / SFYResponder::InvokeBackward 関数を使用してレスポンダに送信します。 イベントを受信したレスポンダは対応するハンドラを呼び出します。 レスポンダイベントはコールバック型イベントです。

[Caution] ユーザーイベント

ユーザーイベントとは、 SFEVT_USER_CLASS_BEGIN(0x8000) から SFEVT_USER_CLASS_END(0xFFFE) の範囲でユーザーが自由に定義できるユーザー独自のイベントのことです。

ユーザーイベントを配信型イベントとして配信するには、 配信規則をトレーサに登録する必要があります。

参照: イベント処理 | イベント一覧

9.2.16. イベントループ

イベントループとは、 BREW 環境から受信した BREW イベントトレーサの配信規則に従い、 ルートSFZRoot)を起点としてレスポンダツリー上の各レスポンダに配信し、 ハンドラを駆動するイベントドリブンな工程の繰り返しのことです。

参照: イベント処理

9.2.17. 配信エンジン

配信エンジンとは、 配信型イベントトレーサに登録された配信規則に基づいて SFYApplication クラスが内部で保持する ルートに関連付けられた SFYDistributer インスタンスとルート以下の レスポンダツリーに配信するアルゴリズム(SFYDistributer インスタンス)のことです。

[Note] 配信エンジンの設定

配信エンジン(SFYDistributer インスタンス)は、 SFYResponder::SetDistributer 関数を使用して SFYApplication クラスが内部で保持する ルートに 1 つだけ設定します。

SFYApplication::SFYApplication コンストラクタで設定済みなので、 SFYApplication クラスを継承するアプリケーションクラスでは配信エンジン (SFYDistributer インスタンス)を設定する必要はありません。

参照: SFYApplication::SFYApplication コンストラクタの内部実装

9.2.18. 描画エンジン

描画エンジンとは、 レスポンダツリーレスポンダ空間に描画するためのアルゴリズム (SFYRenderer インスタンス)のことです。

SFYResponder::Render 関数を呼び出すと、 描画エンジンが起動し、描画が必要なレスポンダに描画イベントを送信します。

描画イベントを受信したレスポンダは描画ハンドラを呼び出して描画処理を行います。

[Note] 描画エンジンの設定

描画エンジン(SFYRenderer インスタンス)は、 SFYResponder::SetRenderer 関数を使用して SFYApplication クラスが内部で保持する ルートに 1 つだけ設定します。

SFYApplication::SFYApplication コンストラクタで設定済みなので、 SFYApplication クラスを継承するアプリケーションクラスでは描画エンジン (SFYRenderer インスタンス)を設定する必要はありません。

参照: SFYApplication::SFYApplication コンストラクタの内部実装

9.2.19. トレーサ

トレーサは、 配信型イベントを配信する規則のことで、 SFYTracer クラスが管理します。

トレーサの配信規則は、 SFYResponder::RegisterTracer / SFYDistributer::RegisterTracer 関数を使用してイベントと関連付けてレスポンダ、または ルートSFZRoot)に設定された SFYDistributer インスタンスに登録します。

配信規則には、 以下の 3 つの要素があります(参照: 標準トレーサ)。

  1. 配信条件. イベントを配信するレスポンダの 状態を指定します。

  2. 処理順序.ハンドラを呼び出す順序を指定します。

  3. 重複条件.イベントを重複して処理するかどうかを指定します。

同一のイベントに対して複数の配信規則をトレーサに登録した場合、 最後に登録した配信規則だけが有効になります (それ以前の配信規則は無効になります)。

[Caution] トレーサに設定可能なイベントの種類

トレーサの設定は、配信型イベントについて行います。 コールバック型イベントの配信規則はトレーサに登録してはいけません。

[Tip] 配信型イベント

配信型イベントとは、 SFYResponder::Distribute 関数を使用して配信するイベントのことです。 このイベントはトレーサの配信規則に基づいて配信され、 配信規則の設定により配信先レスポンダの子孫レスポンダにもイベントを配信できます。 BREW イベントは配信型イベントです。

[Tip] コールバック型イベント

コールバック型イベントとは、 SFYResponder::InvokeForward / SFYResponder::InvokeBackward 関数を使用して送信するイベントのことです。 このイベントは送信先のレスポンダにだけ送信されます。送信先レスポンダの子孫レスポンダには送信されません。 レスポンダイベントはコールバック型イベントです。

参照: 標準トレーサ | イベント

例 9.15. トレーサへの配信規則の登録

SFCError USRResponder::MakeTracer(Void)
{

    // AVK_SOFT1 から AVK_SOFT4 までのキーイベントについて
    // 『処理順序:前面から背面、配信条件:有効状態 ON、重複条件:なし』
    // という配信規則をトレーサに登録する
    return RegisterTracer(
        SFXEventRange(SFEVT_KEY, SFEVT_KEY, AVK_SOFT1, AVK_SOFT4),
        SFYTracer::ORDER_FORWARD, SFYTracer::STATE_ALL, false
    );
}

9.2.20. ハンドラ

ハンドラとは、 イベントを処理する関数のことです。

ハンドラは、SFYResponder::RegisterHandler / SFYDistributer::RegisterHandler 関数を使用してイベントと関連付けてレスポンダ、または ルートSFZRoot)に設定された SFYDistributer インスタンスに登録します。

同一のイベントに対して複数のハンドラを登録することが可能です。 ハンドラは登録順、または登録の逆順に呼び出します。

ハンドラがイベントを処理したとき、 そこで終了するか、 あるいは、無くなるまでハンドラの呼び出しを継続するかの設定が可能です。

例 9.16. ハンドラの登録

SFCError error;

1 つのハンドラを登録する
error = RegisterHandler(SFXEventRange(SFEVT_KEY, SFEVT_KEY, SFP16_BEGIN, SFP16_END), 
                        XANDLER_INTERNAL(OnKey)
        );


複数のハンドラをまとめて登録する
static SFXEventRange::AtomRecConst range[] = {
    {             SFEVT_KEY,              SFEVT_KEY,          SFP16_BEGIN,            SFP16_END},
    {       SFEVT_KEY_PRESS,        SFEVT_KEY_PRESS,          SFP16_BEGIN,            SFP16_END},
    {     SFEVT_KEY_RELEASE,      SFEVT_KEY_RELEASE,          SFP16_BEGIN,            SFP16_END}
};
SFYHandler::RuleRec rule[lengthof(range)];

rule[0].spp = XANDLER_FUNCTION(OnKey);
rule[0].reference = this;
rule[1].spp = XANDLER_FUNCTION(OnKeyPress);
rule[1].reference = this;
rule[2].spp = XANDLER_FUNCTION(OnKeyRelease);
rule[2].reference = this;

error = RegisterHandler(atomic_cast(range), rule, lengthof(range));

9.2.21. トレーサリスト

トレーサリストとは、 SFYTracer クラスが管理する、 スタック型(先頭が最前面、底が最背面)のトレーサの配信規則のリストのことです。

新たに配信規則をレスポンダまたは SFYDistributer インスタンスに登録すると、 配信規則はトレーサリストの先頭にプッシュダウンされます。 一方、条件で指定された配信条件をレスポンダまたは SFYDistributer インスタンスから登録解除するときは、 先頭から検索して条件に一致する配信規則がトレーサリストの先頭から 1 つポップアップされます。

同一イベントに複数個の配信規則が登録されていた場合、 最後に登録された配信規則だけが有効になります。 それ以前の旧い配信規則は無効になります。

[Note] 注意
レスポンダまたは SFYDistributer インスタンスに付き 1 つのトレーサリストが存在します。

9.2.22. ハンドラリスト

ハンドラリストとは、 SFYHandler クラスが管理する、 スタック型(先頭が最前面、底が最背面)のハンドラ(ハンドラ関数)のリストのことです。

新たにハンドラをレスポンダまたは SFYDistributer インスタンスに登録すると、 ハンドラはハンドラリストの先頭にプッシュダウンされます。 一方、条件で指定されたハンドラをレスポンダ、 または SFYDistributer インスタンスから登録解除すると、 先頭から検索して条件に一致するハンドラがハンドラリストの先頭から 1 つポップアップされます。

同一イベントに複数個のハンドラが登録されていた場合、 ハンドラリストを辿る方法には、 先頭(最前面)から末尾(最背面)と、 末尾(最背面)から先頭(最前面)の 2 通りがあります。

[Note] 注意
レスポンダまたは SFYDistributer インスタンスに付き 1 つのハンドラリストが存在します。

9.2.23. 配信型

配信型とは、 SFYResponder::Distribute 関数を使用してイベントをレスポンダに配信し、 ハンドラを呼び出す方法のことです。

具体的には、 SFYResponder::Distribute 関数を呼び出して配信エンジンを起動します。 配信エンジンはトレーサに登録された配信規則に基づいて イベントレスポンダツリー上のレスポンダに配信します。 イベントを受信したレスポンダは対応するハンドラを呼び出します。

[Note] BREW イベントの配信

BREW イベントは配信型です。

[Note] 子孫レスポンダへの配信

コールバック型イベントと異なり、 配信型イベントはトレーサの配信規則の設定により配信先レスポンダの子孫レスポンダに配信することが可能です。

なお、配信型イベントの配信対象は SFYResponder::Distribute 関数を呼び出した時点で構成されているレスポンダツリー上のイベントです。 このイベントを処理している時に動的に新規生成されたレスポンダには配信されません。

9.2.24. コールバック型

コールバック型とは、 SFYResponder::InvokeForward / SFYResponder::InvokeBackward 関数を使用してイベントを送信し、 ハンドラを呼び出す方法のことです。

ハンドラリスト内のハンドラを最前面から呼び出す(ハンドラ登録の逆順に呼び出す)場合は SFYResponder::InvokeForward 関数、 最背面から呼び出す(ハンドラ登録の順に呼び出す)場合は SFYResponder::InvokeBackward 関数を利用します。

SFYResponder::InvokeForward / SFYResponder::InvokeBackward 関数にはイベントを重複して処理するかどうかを表す引数があります。

[Note] レスポンダイベントの送信

レスポンダイベントはコールバック型です。

[Note] 子孫レスポンダへの送信

配信型イベントと異なり、 コールバック型イベントは送信先レスポンダ内だけで処理されます。 このイベントは子孫レスポンダに送信されません。

[Caution] デストラクタ内でのイベント送信

デストラクタを実行する前に自レスポンダの有効状態は無効になっているため、 デストラクタ内で自レスポンダにイベントを送信してはいけません(送信した場合の動作は未定義です)。

9.2.25. タイプ

タイプとは、 レスポンダのクラス識別子として自由に設定できる 4 文字リテラル(four_char_code マクロで定義)のことです。

タイプは SFYResponder::SetType 関数を使用して設定します。 タイプを設定しなかった場合は、親クラスのタイプを継承します。

SFYResponder::GetType 関数を呼び出してレスポンダのタイプの値を参照することにより、 抽象クラスのポインタに格納されたレスポンダの具象クラスを特定できます。

[Caution] 注意事項

タイプはレスポンダのクラスを定義するときにコンストラクタ内で設定します。

小文字アルファベットまたは記号からなる 4 文字リテラルは SophiaFramework UNIVERSE で予約されています(タイプ一覧)。 アプリ開発用には、大文字アルファベット 4 文字からなる 4 文字リテラルを利用してください。

例 9.17. タイプの設定

USRResponder::USRResponder(Void) static_throws
{
    if (static_try()) {

        // タイプは必ずこの場所で設定する
        // このようにすると親クラスのコンストラクタ内でエラーが発生した場合は
        // 親クラスのタイプが保持され、自クラスのコンストラクタ内でエラーが
        // 発生した場合は自クラスのタイプが設定されるようになる
        // 外部からこのクラスを利用する場合にエラーの発生個所を特定しやすくなる
        SetType(four_char_code('U', 'R', 'S', 'P'));

        // その他の初期化処理を記述する

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

例 9.18. タイプの利用

Void USRResponder::PrintType(SFYResponderSmpConstRef param) const
{
    switch (param->GetType()) {

        case SFZWindow::CODE_TYPE:

            TRACE("It is a SFZWindow class.");
            break;

        case SFZDialog::CODE_TYPE:

            TRACE("It is a SFZDialog class.");
            break;

        case SFZTextButtonControl::CODE_TYPE:

            TRACE("It is a SFZTextButtonControl class.");
            break;

        default:

            TRACE("It is an unknown class.");
            break;
    }

    return;
}

9.2.26. ID

ID とは、 レスポンダのインスタンス識別子として自由に設定できる 32ビット符号なし整数(UInt32 型)のことです。

SFYResponder クラスには、SFYResponder::GetChildFront 関数など ID を利用してレスポンダのインスタンスを検索する関数が用意されています。

ID は SFYResponder::SetID 関数を使用して設定します(デフォルト値: 0)。

[Tip] Tip
異なるレスポンダに同一の ID を設定できます。 ID は変更可能です。

例 9.19. ID の設定

SFCError USRResponder::MakeButton(Void)
{
    SFZTextButtonControlSmp button;
    SFCError error(SFERR_NO_ERROR);

    if ((button = SFZTextButtonControl::NewInstance(&error)) != null) {

        if ((error = button->SetParent(GetThis())) == SFERR_NO_ERROR) {

            // テキストボタンコントロールの ID を 100 に設定する
            button->SetID(100);

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

    return error;
}

例 9.20. ID を用いた検索

SFZTextButtonControlSmp USRResponder::GetButton(Void) const
{
    // ID を利用すればクラス変数を用いてレスポンダを管理しなくてもよい

    // ID が 100 であるテキストボタンコントロールを取得する
    return static_pointer_cast<SFZTextButtonControl>(GetChildFront(100));
}

9.2.27. リファレンス

リファレンスとは、 レスポンダのインスタンス識別子として自由に設定できる 4 バイト値(VoidPtr 型)のことです。

SFYResponder::SetReference 関数を使用して、 任意の 4 バイト値を設定できます(デフォルト値: null)。

例 9.21. テキストボタンコントロールへの識別番号の設定とその参照

SFZTextButtonControlSmp _button;
SInt32 i;

// 10 個のテキストボタンコントロールを作成し番号(リファレンス値)を設定する
for (i = 0; i < 10; ++i) {

    // テキストボタンコントロールを作成する
    if ((_button = SFZTextButtonControl::NewInstance(&error)) != null) {

        // テキストボタンコントロールの親 GetThis() に設定する
        error = _button->SetParent(GetThis());
        if (error == SFERR_NO_ERROR) {

            // テキストボタンコントロール識別用番号を設定する
            _button->SetReference(reinterpret_cast<VoidPtr>(i));
        }
    }
}

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

// テキストボタンコントロール識別用番号を取得する
SInt32 number = reinterpret_cast<SInt32>(_button->GetReference());

9.2.28. アタッチメントフレームとコンテントレスポンダ

SFYResponder::SetFrame 関数を使用して、 レスポンダにフレームを装着することが可能です。 このとき、 レスポンダに装着したフレームアタッチメントフレーム、 フレームが装着されたレスポンダをコンテントレスポンダと呼びます。

レスポンダがアタッチメントフレームまたはコンテントレスポンダであるかの判定は、 それぞれ SFYResponder::IsFrame または SFYResponder::HasFrame 関数を使用して行います。

SFYFrame を継承するクラスのインスタンス(フレーム)がアタッチメントフレームの対象となります。

一方、コンテントレスポンダの対象となるレスポンダは、以下の 3 種類です。

  1. SFZWindow を継承するウィンドウ
  2. SFZDialog を継承するダイアログ
  3. SFYMenu を継承するメニュー

図 9.16. アタッチメントフレームとコンテントレスポンダ


アタッチメントフレームとコンテントレスポンダ

アタッチメントフレームとコンテントレスポンダの主な特徴は以下の通りです。

  1. 描画エンジンの観点では、 アタッチメントフレームはコンテントレスポンダの 1 つ下の妹レスポンダとして振舞います。
  2. 状態配信エンジンの観点では、 アタッチメントフレームはコンテントレスポンダの子レスポンダとして振舞います。
  3. アタッチメントフレームの実領域は、 コンテントレスポンダの実領域を外枠やタイトルを描画するためのフレーム余白領域だけ拡大した領域になるように自動的に管理されます。
  4. コンテントレスポンダに対して実領域設定・移動・状態変更・終了などの処理を行うと、 アタッチメントフレームでもそれに伴う処理が自動的に行われます。 このとき、アタッチメントフレームを操作する必要はないのでアタッチメントフレームは透過的に扱えます。
[Note] 注意
実際にフレームを利用する方法に関しては、 こちらを参照してください。

■アタッチメントフレームとコンテントレスポンダの実領域

SFYResponder::SetRealBound 関数を使用して、 コンテントレスポンダの実領域を設定すると、 内部処理により自動的にその実領域をフレーム余白領域だけ拡大した領域がアタッチメントフレームの実領域として設定されます。 この処理は、SFYResponder::SetFrame 関数の内部でも行われます。

逆に、 SFYResponder::SetRealBound 関数を使用して、 アタッチメントフレームの実領域を設定すると、 内部処理により自動的にその実領域をフレーム余白領域だけ縮小した領域がコンテントレスポンダの実領域として設定されます。

[Note] フレーム余白領域

フレーム余白領域とは、 SFYResponder::GetSuitableMargin 関数を呼び出すことで得られる、 外枠やタイトルを描画するための領域です。 SFYResponder::GetSuitableMargin 関数は、 SFYFrame を継承するクラスのインスタンス(フレーム)についてのみ有効です。

フレーム余白領域の計算は内部で自動的に行われるので、 開発者がこの関数を利用する機会はほとんどないでしょう。

■レスポンダツリーにおけるアタッチメントフレーム

SFYResponder::SetParent 関数を呼び出して、 明示的にアタッチメントフレームの親レスポンダを設定することはできません。

SFYResponder::SetFrame 関数を使用してレスポンダに装着した、 アタッチメントフレームのレスポンダツリーにおける扱いは、 以下の点で他のレスポンダと異なることに注意する必要があります。

SFYResponder::GetParent 関数を呼び出して得られるアタッチメントフレームの親レスポンダは、 コンテントレスポンダと同じです。 アタッチメントフレームは、常にコンテントレスポンダの 1 つ下の妹レスポンダであるように内部で管理されます。 また、アタッチメントフレームの実領域は、 コンテントレスポンダの実領域をフレーム用余白領域だけ拡大した領域です。 結果的に、アタッチメントフレームはコンテントレスポンダの外枠として描画されます。

一方、 状態配信エンジンの観点では、 アタッチメントフレームはコンテントレスポンダの子レスポンダとして振舞います。

つまり、アタッチメントフレームはコンテントレスポンダの状態を継承します。 例えば、 コンテントレスポンダの可視状態を ON から OFF に変更すると、 アタッチメントフレームの可視状態もそれに連動して ON から OFF に変わります。

[Caution] アタッチメントフレームの状態フラグについて

アタッチメントフレームの状態フラグは、すべて true に設定する必要があります。

コンテントレスポンダが受信したイベントは、 アタッチメントフレームがコンテントレスポンダの 1 番目の子レスポンダであるものとしてトレーサに登録された規則を利用して配信されます。

[Caution] 注意

アタッチメントフレームとコンテントレスポンダには本当の親子関係や姉妹関係が存在しないので、 この 2 者については親子イベント[SFEVT_RESPONDER_OWNER]は発生しません。

■アタッチメントフレームの透過性

アタッチメントフレームは、以下のように透過的に扱われます。

コンテントレスポンダの実領域を設定すると、 内部処理により自動的にその実領域をフレーム余白領域だけ拡大した領域がアタッチメントフレームの実領域として設定されます。

SFYResponder::GetChildFront などの関数でアタッチメントフレームを取得しようとしても、 アタッチメントフレームは取得できません。 また、SFYResponder::GetChildCount 関数で子レスポンダをカウントしてもアタッチメントフレームはその数に含まれません。

SFYResponder::ToFront などの関数を呼び出して姉妹レスポンダ間でのアタッチメントフレームの位置を変えようとしても、 何も起こりません。コンテントレスポンダもアタッチメントフレームも移動せず、そのままです。

逆に、 姉妹レスポンダ間におけるコンテントレスポンダの位置を変えようとしてそれを呼び出した場合、 コンテントレスポンダと共にアタッチメントフレームも一緒に移動します。 アタッチメントフレームは、常にコンテントレスポンダの 1 つ下の妹レスポンダであるように内部で管理されます。

SFYResponder::Terminate 関数を呼び出してコンテントレスポンダを終了すると、 アタッチメントフレームは自動的にコンテントレスポンダから切り離されて見えなくなり、 他のレスポンダに装着可能な通常のフレームに戻ります。

アタッチメントフレームを終了した場合は、 アタッチメントフレームがコンテントレスポンダから切り離され、見えなくなるだけです。 コンテントレスポンダには何の影響も及ぼしません。