Palm OS Programmer’s Companion Volume I/4-9 - project-enigma

Palm OS Programmer’s Companion Volume I/4-9

>> Site top >> Misc >> In my palm >> Palm開発ドキュメントの和訳 >> Palm OS Programmer’s Companion Volume I >> Palm OS Programmer’s Companion Volume I/4-9

最終更新日付:2014/01/01 00:00:00

← 8 節に戻る ↑4 章トップへ 10 節に進む →

4-9 カテゴリ

 

カテゴリを使えば、レコードを論理的に分類してリストにすることができます。ユーザーインターフェースにおいては、カテゴリは通常フォームのタイトルバーや、単一レコードを編集するダイアログにポップアップリストとして表示されます。

他のポップアップリストを作成するのと同じように、カテゴリポップアップリストを作成することができます。リストリソースを作成し、ポップアップトリガーのリソースを作成して、幅を 0 に、トリガーのリスト ID にリストリソースの ID を設定します。カテゴリポップアップリストの操作はカテゴリ API を使用して行ないます。「Palm OSProgrammer’s API Reference」の "Categories" の章を参照して下さい。

ほとんどの場合、カテゴリポップアップリストは以下の関数コールで処理できます。

カテゴリトリガーを選択した時に起きる事象をより細かく制御したいと考えない限り、Category.h で宣言されているその他の関数を使う必要は通常ありません。

このセクションでは、カテゴリのユーザーインターフェースについて説明します。カテゴリがデータベース内にどのように保存され、どのように管理されるかについては、「6 ファイルとデータベース」を参照して下さい。

 

データベースカテゴリの初期化

カテゴリ API を使用する前に、データベースを適切に設定する必要があります。カテゴリ関数は特定の位置で情報を探します。そこに必要な情報がなければ、関数は失敗します。

カテゴリ情報はデータベースのアプリケーション情報ブロック内にある AppInfoType構造体に保存されます。本書の 「6 ファイルとデータベース」で説明しているように、アプリケーション情報ブロックはデータベースが必要とする情報を全て格納することができます。カテゴリ API を使いたい場合、アプリケーション情報ブロックの最初のフィールドは AppInfoType 構造体でなければなりません。

AppInfoType 構造体はカテゴリ名とカテゴリインデックスおよびカテゴリのユニークID を対応付けます。カテゴリ名はユーザーインターフェース上に表示されます。カテゴリインデックスは、データベースレコードをカテゴリに関連付けるためのものです。つまり、データベースレコードの attribute フィールドは、そのレコードが所属するカテゴリのインデックスを保持しています。カテゴリのユニーク ID はデスクトップコンピュータとの同期の際に使用されます。

AppInfoType 構造体を初期化するためには、CategoryInitialize をコールしてカテゴリ名の一覧を含む文字列リソースを渡します。この関数は必要な数のカテゴリインデックスとユニーク ID を作成します。必要なことは、データベースを最初に作成したとき、またはデータベースのアプリケーション情報ブロックを新規に設定したときにこの関数をコールすることだけです。

文字列リストリソースは appInfoStringsRsc ('tAIS') タイプのリソースです。このリソースには、ユーザーがアプリケーションを最初に起動したときにユーザーが目にする定義済みのカテゴリが含まれています。CategoryInitialize のコールが、appInfoStringsRsc リソースを使用する唯一の場所であることに注意して下さい。このリソースを作成する際、以下のガイドラインに従って下さい。

リスト 4.3 に、データベースを作成してアプリケーション情報ブロックで初期化する関数の例を示します。アプリケーション情報ブロックはデータベースに保存されるため、メモリのアロケートには MemHandleNew ではなく DmNewHandle を使用することに注意して下さい。

リスト 4.3 アプリケーション情報ブロックを使ったデータベースの作成

typedef struct {
    AppInfoType appInfo;
    UInt16 myCustomAppInfo;
} MyAppInfoType;

Err CreateAndOpenDatabase(DmOpenRef *dbPP, UInt16 mode)
{
    Err error = errNone;
    DmOpenRef dbP;
    UInt16 cardNo;
    MemHandle h;
    LocalID dbID;
    LocalID appInfoID;
    MyAppInfoType *appInfoP;

    // Create the database.
    error = DmCreateDatabase (0, MyDBName, MyDBCreator, MyDBType, false);
    if (error) return error;

    // Open the database.
    dbP = DmOpenDatabaseByTypeCreator(MyDBType, MyDBCreator, mode);
    if (!dbP) return (dmErrCantOpen);

    // Get database local ID and card number. We need these to
    // initialize app info block.
    if (DmOpenDatabaseInfo(dbP, &dbID, NULL, NULL, &cardNo, NULL))
        return dmErrInvalidParam;

    // Allocate app info in storage heap.
    h = DmNewHandle(dbP, sizeof(MyAppInfoType));
    if (!h) return dmErrMemError;

    // Associate app info with database.
    appInfoID = MemHandleToLocalID (h);
    DmSetDatabaseInfo(cardNo, dbID, NULL, NULL, NULL, NULL, NULL,
                      NULL, NULL, &appInfoID, NULL, NULL, NULL);

    // Initialize app info block to 0.
    appInfoP = MemHandleLock(h);
    DmSet(appInfoP, 0, sizeof(MyAppInfoType), 0);

    // Initialize the categories.
    CategoryInitialize((AppInfoPtr)appInfoP, MyLocalizedAppInfoStr);

    // Unlock the app info block.
    MemPtrUnlock(appInfoP);
    // Set the output parameter and return.

    *dbPP = dbP;
    return error;
}

 

 

カテゴリポップアップトリガーの初期化

フォームをオープンした際、表示されるカテゴリポップアップトリガーにテキストを指定する必要があります。そのためには、CategoryGetName 関数を使用して AppInfoType 構造体内の名前を検索し、次に CategorySetTriggerLabel をコールしてポップアップトリガーに設定します。

アプリケーションのメインフォームでは、通常、選択されているカテゴリのインデックスをプリファレンスに保存しておき、次にアプリケーションが起動した際にそれを復元します。

単一レコードの情報を表示するようなフォームでは、レコードのカテゴリをポップアップリストで表示するべきです。データベースの各レコードは attribute フィールドに自身のカテゴリを保存しています。レコードの属性は DmRecordInfo 関数を使用して取得でき、それと dmRecAttrCategoryMask の論理積をとることでカテゴリインデックスを取得できます。

リスト 4.4 に、特定のデータベースレコードのカテゴリにマッチするラベルをトリガーに設定する方法を示します。

リスト 4.4 カテゴリトリガーラベルの設定

UInt16 attr, category;
Char categoryName [dmCategoryLength];
ControlType *ctl;

// If current category is All, we need to look
// up category.
if (CurrentCategory == dmAllCategories) {
    DmRecordInfo (AddrDB, CurrentRecord, &attr, NULL, NULL);
    category = attr & dmRecAttrCategoryMask;
} else
    category = CurrentCategory;

CategoryGetName(AddrDB, category, categoryName);
ctl = FrmGetObjectPtr(frm,FrmGetObjectIndex(frm, objectID));
CategorySetTriggerLabel(ctl, categoryName);

 

 

カテゴリポップアップリストの処理

カテゴリポップアップトリガーがタップされたら、CategorySelect をコールします。つまり、カテゴリトリガーの ID にマッチする ID が格納された ctlSelectEvent に応答して CategorySelect をコールするということです。CategorySelect 関数はポップアップリストを表示し、ユーザーによる選択を処理し、必要に応じて「カテゴリの編集」ダイアログを表示し、ユーザーの選択したカテゴリ名をポップアップトリガーのラベルに設定します。

 

CategorySelect のコール

典型的な CategorySelect の呼び出しを以下に示します。

リスト 4.5 CategorySelect の呼び出し

categoryEdited = CategorySelect(AddrDB, frm, ListCategoryTrigger,
                                ListCategoryList, true, &category,
                                CategoryName, 1,
                                categoryDefaultEditCategoryString);

 

この例では、以下のパラメータを指定しています。

NOTE

定数 categoryDefaultEditCategoryString と categoryHideEditCategory は 3.5 新フィーチャセットが存在する場合のみ定義されます。より詳細な互換性情報については「Palm OS Programmer’s API Reference」の CategorySelect 関数の説明を参照して下さい。

 

復帰値の解釈

CategorySelect の復帰値は少しばかり複雑です。CategorySelect はユーザーがカテゴリリストを編集した場合 true を返し、それ以外の場合は false を返します。つまり、カテゴリ編集アイテムを選択してカテゴリ名の追加、編集、削除をした場合、関数はtrue を返します。カテゴリ編集が選択されなければ、関数は false を返します。ほとんどの場合、カテゴリを編集することなくリスト内の既存アイテムを選択するだけなので、そのような場合には CategorySelect は false を返します。

このことは、なんらかのアクションを実行する必要性を確認するのに復帰値に単純に頼れないことを意味します。そのかわり、CategorySelect 関数に渡すカテゴリインデックス(のコピー)を保存しておき、関数が返すインデックスと比較する必要があります。以下に例を示します。

リスト 4.6 CategorySelect の復帰値

Int16 category;
Boolean categoryEdited;

category = CurrentCategory;

categoryEdited = CategorySelect(AddrDB, frm, ListCategoryTrigger,
                                ListCategoryList, true, &category,
                                CategoryName, 1,
                                categoryDefaultEditCategoryString);

if ( categoryEdited || (category != CurrentCategory)) {
    /* user changed category selection or edited category list.
       Do something. */
}

 

別のカテゴリが選択された場合、以下の2つのうち、どちらかをすることになるでしょう。

CategorySelect 関数はカテゴリ編集ダイアログに従ってユーザーデータベースを変更することに注意して下さい。具体的には、データベースの AppInfoType 構造体の要素を追加、削除、リネームします。レコードを含むカテゴリが削除されると、これらのレコードは Unfiled カテゴリに移動されます。既存のカテゴリが別の既存カテゴリと同じ名前に変更されると、ユーザー確認の上で、古いカテゴリから新しいカテゴリにレコードが移動されます。そのため、CategorySelect 呼び出し後にカテゴリリストの管理について心配する必要はありません。

 

 

 

← 8 節に戻る ↑4 章トップへ 10 節に進む →

 

 


Copyright(C) 2005-2017 project-enigma.
Generated by CL-PREFAB.