このドキュメントについて | 用語集 | アプリケーションの記述方法 | ユーザー インタラクションの検出方法 | 複数の UI の統合
ほとんどのアプリケーションは 2 種類以上の Flex UI コンポーネントから構成されます。アプリケーションが複雑になると、複数の EventListener を使用してユーザーの操作をモニターします。したがって各オブジェクトの EventHandler は、共用されたり、互いに依存することがあります。
前のセクションのアドレス帳の例は FlexTable
、FlexList
、FlexButton
と、対応する EventHandler TableSelectionChanged
、ItemStateChanged
、ActionPerformed
で構成されていました。
このアプリケーションのデザインでは 、 EventHandler が他の EventHandler を呼び出す場合があります。例えば、ユーザーがアドレス帳のエントリの名前を変更したときは TableSelectionChanged
が呼び出されます。ユーザーのインタラクションによっては TableSelectionChanged
が ItemStateChanged
を呼び出してリストを更新します。
ここでは次に示す Flex UI コンポーネントを使ってメモ帳アプリケーションを作成し、複数ファイルへの保存やファイル操作用のメニューを実装します。
複数のファイルにデータを保存し、ユーザーがメニューからファイル操作を選択できるメモ帳アプリケーションの作成手順を、次に示します。
Notepad2App
を宣言します。FlexMenu
をフレームにアタッチします。CreateDialogUI
を呼び出してダイアログをアタッチします。FlexTextArea
をフレームにアタッチし、ユーザー インターフェイスを表示します。CreateDialogUI
を追加してアプリケーションのダイアログを生成します。MenuItemChosen
を追加してメニュー イベントを処理します。ItemStateChanged
を追加してリスト イベントを処理します。ItemStateChanged
に追加します。
ヘッダー ファイル notepad2.h
で、クラス Notepad2App
を宣言します。
(リソース | ヘッダー | ソース)
#ifndef _NOTEPAD2_H_ #define _NOTEPAD2_H_ #include <ui/appbase.h> #include <toolkit/lisact.h> #include <toolkit/adptext.h> #include <toolkit/lisitem.h> class Notepad2App : public ItemListenerInterface, public MenuAdapter, public AppBase { public: // アプリケーションの初期画面の UI を作成するために、SetAppContext を // オーバーライドします void SetAppContext(const TCHAR *context); // 初期画面用の UI を作成するためのヘルパー関数 Result AttachNotepad2AppUI(void); Result CreateDialogUI(static const TCHAR *title, FlexDialog **dialog ); // MenuItemChosen はメニューの MenuEvents を処理します void MenuItemChosen(MenuEvent& event); // ItemStateChanged はリストの ItemEvents を処理します void ItemStateChanged(ItemEvent& event ); // アプリケーションを終了する為の Exit をオーバーライドします virtual void Exit(void); // グローバルなコンポーネント FlexTextArea *_textDisplay; FlexDialog *_saveDialog; FlexDialog *_openDialog; // Open ダイアログ ボックスの id を保持します int _dialogOpen; }; // メニュー アイテム id を列挙します const FlexComponentID NEW_MENU_ITEM = 0; const FlexComponentID SAVE_MENU_ITEM = 1; const FlexComponentID OPEN_MENU_ITEM = 2; #endif /* _NOTEPAD2_H_ */
ソース ファイル notepad2.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 <pos/fsmgr.h> #include <pos/file.h> #include <resapp/resapp.h> #include <locale/locale.h> #include "resource.h" #include "notepad2.h" // アプリケーションのメニュー用文字列定数を作成します static const TCHAR *MENU_ITEMS[3] = {_TEXT("New"), _TEXT("Save"), _TEXT("Open")}; // テキストを保持するバッファを作成します TCHAR *_notepad2TextString; // アプリケーションを登録します class Notepad2ResidentApplication : public ResidentApplication { public: Notepad2ResidentApplication() : ResidentApplication(_TEXT("notepad2")) {}; virtual AppBase *CreateAppBase(void) {return new Notepad2App;} }; static Notepad2ResidentApplication notepadApp2; static AppNameAttribute notepadApp2Name(¬epadApp2, NOTEPAD2_APP_TEXT); // アプリケーションを作成します void Notepad2App::SetAppContext(const TCHAR *) { _dialogOpen = 0; if (AttachNotepad2AppUI() == FAILURE) { EC_WARN("Unable to build Notepad2 application."); } // テキスト バッファの領域を割り当てます _notepad2TextString = new TCHAR[600]; }
フラグ _dialogOpen
には開いているダイアログに対応した値が入るので、現在開いているダイアログがないことを示すために SetAppContext
内で値をリセットします。
メソッド AttachNotepad2AppUI
で、アプリケーションにフレームをアタッチします。
(リソース | ヘッダー | ソース)
Result Notepad2App::AttachNotepad2AppUI(void) { FlexFrame *frame; FlexMenu *menu; FlexMenuButton *menuButton; // アプリケーションのメインのフレームを作成します frame = theUIFactory->CreateFlexFrame(HINT_FRAME_WITH_NO_CLOSE_BUTTON, NOTEPAD2_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);
メソッド AttachNotepadApp2UI
で、FlexMenu
をフレームにアタッチしてファイル操作を処理します。
(リソース | ヘッダー | ソース)
menu = theUIFactory->CreateFlexMenu(HINT_PULL_DOWN_MENU, NOTEPAD2_FILE_MENU_TEXT); if (menu == NULL) { return FAILURE; } for ( int i = 0; i < 3; i++) { menuButton = theUIFactory->CreateFlexMenuButton( 0, MENU_ITEMS[i], (MenuItemID) i); if (menuButton == NULL) { return FAILURE; } else { menu->Add(menuButton); } } menu->AddMenuListener(*this); frame->Add(menu);
メソッド CreateFlexMenuButton
を呼び出して、各 FlexMenuButton
を作成します。
メニュー ボタンの作成に成功すれば、それをメニューに追加します。
メニューを作成した後に、AddMenuListener
メソッドを使用してメニューの選択を処理する EventHandler を追加し、それからメニューをフレームに追加します。
AttachNotepadApp2UI
で、ヘルパー関数 CreateDialogUI
を呼び出してダイアログを作成します。
(リソース | ヘッダー | ソース)
if ( CreateDialogUI(NOTEPAD2_SAVE_DIALOG_TEXT, &(_saveDialog)) == FAILURE) { return FAILURE; } if ( CreateDialogUI(NOTEPAD2_OPEN_DIALOG_TEXT, &(_openDialog)) == FAILURE) { return FAILURE; }
_saveDialog
と _openDialog
はグローバル変数なので、"&"
シンボルを使ってそのアドレスを CreateDialogUI
に渡します。
同じメソッドで、FlexTextArea
をフレームにアタッチした後、ユーザー インターフェイスを表示させます。
(リソース | ヘッダー | ソース)
// アプリケーションのテキスト表示を作成します _textDisplay = theUIFactory->CreateFlexTextArea(0); if (_textDisplay == NULL) { return FAILURE; } // テキスト表示の属性を設定します _textDisplay->SetColumns(75); _textDisplay->SetRows(7); _textDisplay->SetMaxChars(600); // テキスト表示をフレームに追加します frame->Add(_textDisplay); // フレームを表示し、SUCCESS を返します frame->SetVisible(TRUE); return SUCCESS; }
notepad2.cpp
で、ヘルパー関数 CreateDialogUI
を追加してアプリケーションのダイアログを作成します。
(リソース | ヘッダー | ソース)
Result Notepad2App::CreateDialogUI(static const TCHAR *title, FlexDialog **dialog) { *dialog = theUIFactory->CreateFlexDialog(1, title); if (*dialog == NULL) { return FAILURE; } DialogLayout *offsetDialogLM = new DialogLayout(); (*dialog)->SetLayout(offsetDialogLM); FlexLabel *label = theUIFactory->CreateFlexLabel(0, title); FlexList *list = theUIFactory->CreateFlexList(0, 4); if (list == NULL) { return FAILURE; } list->SetSizingPreference(FlexComponent::SPT_USE_PREF_SIZE); if (list->Add(NOTEPAD2_FILE1) == FAILURE) { return FAILURE; } if (list->Add(NOTEPAD2_FILE2) == FAILURE) { return FAILURE; } if (list->Add(NOTEPAD2_FILE3) == FAILURE) { return FAILURE; } if (list->Add(NOTEPAD2_FILE4) == FAILURE) { return FAILURE; } list->AddItemListener(*this); (*dialog)->Add(label); (*dialog)->Add(list); this->Add(*dialog); return SUCCESS; }
DialogLayout
を使用してダイアログのコンポーネントを配置します。DialogLayout
はダイアログ ボックスの小さな領域を管理するために特別にデザインされたレイアウトです。
FlexList
は Flex UI コンポーネントで、文字列データのリストを保持します。ここではファイル名を保持しています。FlexList
と FlexMenu
は、FlexMenu
ではメニュー ボタンを押したときにイベントが生成されるのに対して、FlexList
は現在選択中の項目が変化したときにイベントが生成される点が異なります。このアプリケーションでは、FlexList
を使用してテキスト バッファの保存や読み込みができるファイルを表示します。ファイルごとに FlexList
メソッド Add
を使用して、ファイル名をリストに追加します。
リストを作成した後で、AppBase
メソッド Add
を使用してダイアログをシステムにアタッチします。
notepad2.cpp
に、EventHandler の MenuItemChosen
を追加してメニュー イベントを処理します。
(リソース | ヘッダー | ソース)
void Notepad2App::MenuItemChosen(MenuEvent& event ) { uint32 id = (uint32)event._menuItemID; if (_dialogOpen < 1) { switch (id) { case NEW_MENU_ITEM: _textDisplay->SetText(_TEXT("")); break; case SAVE_MENU_ITEM: _dialogOpen = id; _saveDialog->SetVisible(TRUE); break; case OPEN_MENU_ITEM: _dialogOpen = id; _openDialog->SetVisible(TRUE); break; } } }
_menuItemID
には選択中のメニュー項目の id
が入ります。switch 文では id
を使用してどの FlexMenuButton
が選択されたかを判断し、それに応じて適切なダイアログを表示し、_dialogOpen
を対応する値に設定します。
notepad2.cpp
に、EventHandler の ItemStateChanged
を追加してリスト イベントを処理します。
(リソース | ヘッダー | ソース)
void Notepad2App::ItemStateChanged(ItemEvent& event ) { // SAVE と OPEN のためのファイル ポインタと、 // ファイル名を格納する文字列を作成します File *myFile; const TCHAR *filename; FlexList *list = (FlexList *)event.GetSource(); uint32 index = event.GetIndex(); switch (index) { case 0: filename = NOTEPAD2_FILE1; break; case 1: filename = NOTEPAD2_FILE2; break; case 2: filename = NOTEPAD2_FILE3; break; case 3: filename = NOTEPAD2_FILE4; break; }
メソッド GetIndex
を使用して選択中の文字列に対応する番号を index
に読み込みます。switch 文では、この index
を使って保存や読み込みに使用するファイル名を設定します。
ファイルの Save (保存)と Revert (読み込み)のコードを ItemStateChanged
に追加します。
(リソース | ヘッダー | ソース)
// SAVE がクリックされたかどうかチェックします if (_dialogOpen == SAVE_MENU_ITEM) { // バッファの内容を取得します _textDisplay->GetText(_notepad2TextString, 600); // ファイルを CREATE と READ_WRITE 属性で開きます myFile = theFileStoreManager.Open(filename, O_CREAT | O_RDWR ); // バッファの内容をファイルへ書き込み、 // ファイルを閉じます myFile->Write((uint8 *)_notepad2TextString, 600); myFile->Close(); // ダイアログを閉じます _saveDialog->SetVisible(FALSE); } // OPEN がクリックされたかどうかチェックします else if (_dialogOpen == OPEN_MENU_ITEM) { // ファイルがすでに存在するかどうかチェックします if (theFileStoreManager.FileExists(filename)) { // ファイルを READ_ONLY で開き、内容をバッファに読み込み、 // 操作終了後にファイルを閉じます myFile = theFileStoreManager.Open(filename, O_RDONLY ); myFile->Read((uint8 *)_notepad2TextString, 600); myFile->Close(); // バッファの内容を表示します _textDisplay->SetText(_notepad2TextString); } // ダイアログを閉じます _openDialog->SetVisible(FALSE); } // リスト項目の選択を解除します list->Deselect(index); // ダイアログ ボックスが閉じているように設定します _dialogOpen = 0; }
このドキュメントについて | 用語集 | アプリケーションの記述方法 | ユーザー インタラクションの検出方法 | 複数の UI の統合