GEOS-SC : Flex UI : Flex UI 使用法 : ユーザー インタラクションの検出方法

このドキュメントについて | 用語集 | アプリケーションの記述方法 | ユーザー インタラクションの検出方法 | 複数の UI の統合


アプリケーションが実行する仕事のほとんどは、Flex UI コンポーネントと EventListener で処理されます。Flex UI の各オブジェクトは、オブジェクトへのユーザー インタラクションを、対応する EventListener を使ってチェックできます。コンポーネントがイベントを検出すると、EventListener が適切な EventHandler を呼び出して応答を実行します。

例えばアドレス帳のアプリケーションは、エントリを表示する FlexTable、登録された名前の一覧を表示する FlexList、表示中のエントリの電話番号をダイアルする FlexButton 等で構成できます。

これらのオブジェクトはそれぞれがイベントをチェックする EventListener を持っており、イベントを処理するコードはそれぞれの EventHandler に記述されています。

ここではメモ帳のアプリケーションを作成します。このアプリケーションでは次の Flex UI コンポーネントを使用して、テキストの入力、消去、保存、以前に保存したテキストの読み込みができます。

テキストの消去、保存、読み込みができるメモ帳アプリケーションの作成手順を次に示します。

  1. ヘッダー ファイルでクラス NotepadApp を宣言します。
  2. アプリケーションを登録してユーザー インターフェイスを作成します。
  3. フレームをシステムにアタッチします。
  4. ボタンを配置するための FlexPanel を作成します。
  5. ヘルパー関数 CreateButton を呼び出してパネルにボタンを追加します。
  6. FlexTextArea をフレームにアタッチしてユーザー インターフェイスを可視に設定します。
  7. ヘルパー関数 CreateButton を追加してアプリケーションのボタンを生成します。
  8. アプリケーションでボタンが押された時の処理を記述する EventHandler の ActionPerformed を追加します。
  9. ActionPerformed にファイル保存用のコードを追加します。
  10. ActionPerformed にファイル読み込み用のコードを追加します。
  11. アプリケーションをコンパイルして実行します。


ヘッダー ファイル notepad.h でクラス NotepadApp を宣言します。 (リソース | ヘッダー | ソース)


#ifndef _NOTEPAD_H_
#define _NOTEPAD_H_

#include <ui/appbase.h>
#include <toolkit/lisact.h>          
#include <toolkit/panel.h>

class NotepadApp : public ActionListenerInterface, public AppBase {
public:

    void SetAppContext(const TCHAR *context);
    
    Result AttachNotepadAppUI(void);
    Result CreateButton(const TCHAR *title, FlexComponentID buttonID);
    
    void ActionPerformed(ActionEvent& event);

    virtual void Exit(void);

    FlexPanel           *_buttonPanel;
    FlexTextArea        *_textDisplay;
};

const FlexComponentID NEW_BUTTON = 0;
const FlexComponentID SAVE_BUTTON = 1;
const FlexComponentID REVERT_BUTTON = 2;

#endif /* _NOTEPAD_H_ */

このアプリケーションでは EventListener を使用して New、Save、Revert の各ボタンをモニターするため、クラス ActionListenerInterface を基本クラスのリストに追加します。ActionListener はボタンが押された場合にそれを検出する EventListener です。

AttachNotepadAppUISetAppContext のヘルパー関数で、アプリケーションの初期画面を作成します。
CreateButtonAttachNotepadAppUI のヘルパー関数で、初期画面のボタンを作成します。

ActionPerformed は EventHandler メソッドで、ボタンが押された時の処理を制御します。

FlexComponent の _buttonPanel_textDisplay をグローバルに宣言し、複数のメソッドからアクセスできるようにします。

後で作成するボタンに対応させて FlexComponentID の値を定義します。この値はボタンの識別に使います。


ソース ファイル notepad.cpp で、アプリケーションを登録してユーザー インターフェイスを作成します。 (リソース | ヘッダー | ソース)


#include <kernel/geode.h>       
#include <kernel/system.h>
#include <flexui/demoui.h>
#include <toolkit/uifact.h>
#include <toolkit/lmdialog.h>
#include <toolkit/lmflow.h> 
#include <fs/fsmgr.h>
#include <fs/file.h>
#include <resapp/resapp.h>
#include <locale/locale.h>
#include "resource.h"
#include "notepad.h"

//  テキストを保持するバッファを作成します。
TCHAR *_notepadTextString;

// アプリケーションをシステムに登録します。
class NotepadResidentApplication : public ResidentApplication {
 public:
    NotepadResidentApplication() : ResidentApplication(_TEXT("notepad")) {};
    virtual AppBase *CreateAppBase(void) {return new NotepadApp;}
};

static NotepadResidentApplication notepadApp;
static AppNameAttribute notepadAppName(¬epadApp, NOTEPAD_APP_TEXT);

// アプリケーションを作成します。
void
NotepadApp::SetAppContext(const TCHAR *)
{
    if (AttachNotepadAppUI() == FAILURE) { 
        EC_WARN("Unable to build Notepad application."); 
    }

    _notepadTextString = new TCHAR[600]; 
}

ユーザー インターフェイスが作成できたことを確認するために、ヘルパー関数 AttachNotepadAppUI の結果を返します。ユーザー インターフェイスのコンポーネントが作成できなかったときは、システムからユーザーに通知されます。

new を使用してバッファ用のメモリ領域を割り当てます。


ヘルパー関数 AttachNotepadAppUI で、アプリケーションにフレームをアタッチします。 (リソース | ヘッダー | ソース)


Result
NotepadApp::AttachNotepadAppUI(void)
{

    FlexFrame *frame = 
        theUIFactory->CreateFlexFrame(HINT_FRAME_WITH_NO_CLOSE_BUTTON, NOTEPAD_APP_TEXT);
    if (frame == NULL) { return FAILURE; }

    VerticalFlowLayout *mainFrameLayout 
        = new VerticalFlowLayout(   10, 
                                    VerticalFlowLayout::Y_JUSTIFY_CENTER, 
                                    LayoutManagerInterface::X_ALIGN_LEFT);
    if (mainFrameLayout == NULL) { return FAILURE; }

    frame->SetLayout(mainFrameLayout);
    this->Add(frame);

VerticalFlowLayout では、コンポーネントの左端を整列させた状態で垂直方向にはコンポーネント間に 10 ピクセルの間隔を置いて画面中央に均等配置し、frame のレイアウトを整えます。


次に同じ AttachNotepadAppUI メソッドに、ボタン用の FlexPanel を作成します。 (リソース | ヘッダー | ソース)


    _buttonPanel = new FlexPanel;
    if (_buttonPanel == NULL) { return FAILURE; }

    HorizontalFlowLayout *buttonPanelLayout = new HorizontalFlowLayout(8);
    if (buttonPanelLayout == NULL) { return FAILURE; }

    _buttonPanel->SetLayout(buttonPanelLayout);

FlexPanel は、ユーザー インターフェイスの一部のコンポーネントをグループ化し、アプリケーションの他の部分から独立して制御する必要がある場合に使います。ここではボタンを水平方向に並べて配置するために、FlexPanel で 3 個のボタンをグループ化し、HorizontalFlowLayout を適用します。


さらに同じメソッド AttachNotepadAppUI の中で、ヘルパー関数 CreateButton を呼び出してボタンをパネルに追加します。 (リソース | ヘッダー | ソース)


    if ( CreateButton(NOTEPAD_NEW_BUTTON_TITLE, NEW_BUTTON) == FAILURE )
    { return FAILURE; }
    if ( CreateButton(NOTEPAD_SAVE_BUTTON_TITLE, SAVE_BUTTON) == FAILURE )
    { return FAILURE; }
    if ( CreateButton(NOTEPAD_REVERT_BUTTON_TITLE, REVERT_BUTTON) == FAILURE )
    { return FAILURE; }
        
    frame->Add(_buttonPanel);

各ボタンに、対応するタイトルの文字列と識別用の FlexComponentID を渡します。CreateButton の呼び出しではボタンの作成に成功してパネルに追加された場合に SUCCESS が返されます。CreateButton の呼び出しが成功しなかった場合は AttachNotepadAppUI から FAILURE が返され、アプリケーションの作成ができなかったことがシステムからユーザーに通知されます。

ボタンを作成した後で、_buttonPanel をフレームにアタッチします。 _buttonPanel 上のボタンは水平方向に並べて配置され、_buttonPanel 自体はフレーム上で垂直方向に並べて配置されます。


AttachNotepadAppUI メソッドに FlexTextArea を追加した後、フレームを表示します。 (リソース | ヘッダー | ソース)

    
    _textDisplay = theUIFactory->CreateFlexTextArea(0);
    if (_textDisplay == NULL) { return FAILURE; }

    _textDisplay->SetColumns(75);
    _textDisplay->SetRows(7);  
    _textDisplay->SetMaxChars(600);

    frame->Add(_textDisplay);

    frame->SetVisible(TRUE);
    return SUCCESS;

}

テキスト表示の最大文字数を設定して、アプリケーションの後の部分でバッファ サイズを越えないようにすることが重要です。テキスト表示を正しく設定した後は、フレームをシステムにアタッチし、ユーザー インターフェイスをユーザーに見えるようにします。


notepad.cpp ファイルに、 CreateButton メソッドを追加します。 (リソース | ヘッダー | ソース)


Result
NotepadApp::CreateButton(const TCHAR *title, FlexComponentID buttonID)
{
    
    FlexButton *button = 
	theUIFactory->CreateFlexButton(0, title);
    if (button == NULL) { return FAILURE; }

    _buttonPanel->Add(button);

    button->AddActionListener(*this);

    button->SetID(buttonID);
    return SUCCESS;

}

ヘルパー関数 CreateButton は、ユーザー インターフェイス用のボタンを作成し、SUCCESS または FAILURE を返します。 ボタンの作成にはこのようなヘルパー関数を使用すると、コードの繰り返しが避けられる上に、追加されてゆく各ボタンの記録が残ります。この例では、作成したボタンの記録を取るのにヘッダー ファイルに保存した buttonID を使います。

AddActionListener メソッドは、ActionListener がモニターするオブジェクトのリストにボタンを追加します。


notepad.cpp ファイルに、 ActionPerformed メソッドを追加します。 (リソース | ヘッダー | ソース)


void
NotepadApp::ActionPerformed(ActionEvent& event )
{

    File *myFile;       

    FlexComponentID id = (event.GetSource())->GetID();

    switch(id) {

    case NEW_BUTTON: 
        _textDisplay->SetText(_TEXT(""));
        break;

ActionPerformed メソッドはすべてのボタン イベントを扱うため、GetID メソッドを使用してイベントを生成したボタンの ID を取得します。この ID を使用して、ActionPerformed を呼び出したオブジェクトを決定します。

ユーザーが New ボタンを押した場合は、SetText メソッドを使用してテキストを全部消去します。


ActionPreformed メソッドに、ファイル保存用のコードを追加します。 (リソース | ヘッダー | ソース)


    case SAVE_BUTTON:
        
        _textDisplay->GetText(_notepadTextString, 600);
		
        myFile = theFileStoreManager.Open(_TEXT("/int/tempfile"), O_CREAT | O_RDWR );
                
        myFile->Write((uint8 *)_notepadTextString, 600);
        myFile->Close();
        break;		

ユーザーが Save ボタンを押した場合は、バッファをファイルに保存します。 ファイルに書き込んだ後は閉じるのを忘れないようにします。


ActionPreformed メソッドに、ファイル読み込み用のコードを追加します。 (リソース | ヘッダー | ソース)


    case REVERT_BUTTON:
        
        if (theFileStoreManager.FileExists(_TEXT("/int/tempfile"))) {

            myFile = theFileStoreManager.Open(_TEXT("/int/tempfile"), O_RDONLY );
            myFile->Read((uint8 *)_notepadTextString, 600);
            myFile->Close();
	
            _textDisplay->SetText(_notepadTextString);	
        }
        break;		
    }
}

ユーザーが Revert ボタンを押した場合は、FileStoreManager メソッド FileExists を使用して、指定されたファイルが存在することをチェックし、以前に保存したファイルをバッファに読み込みます。


アプリケーションをコンパイルして実行します。


このドキュメントについて | 用語集 | アプリケーションの記述方法 | ユーザー インタラクションの検出方法 | 複数の UI の統合