Palm Programmer's Laboratory
Palm OS Programmer's Companion Volume I/4-8
4-8 リスト
リストオブジェクトはボックス内に選択肢を縦に並べて表示します。リスト内の選択されている行は反転表示されます。
図 4.18 リスト
リストは静的なデータのためのものです。ユーザーはあらかじめ決められた数のアイテムから選択することができます。例としては、以下のようなものがあります。
- Datebook の時刻編集ウィンドウにおける時刻一覧
- カテゴリのポップアップリスト(「 4-9 カテゴリ 」 参照 )
表示できる数以上の選択肢がある場合、システムは表示されている最初と最後の要素の右側に小さな矢印(スクロールインジケータ)を描画します。スクロールインジケータをペンでタップすると、リストはスクロールします。下方向にスクロールした場合、リストに表示するだけの十分な要素数があれば、スクロール前に最後に位置していた要素が最初に表示されるようにスクロールします。それ以外の場合、最後の要素がリスト上で一番最後に表示されるようにスクロールされます。上方向のスクロールでは、丁度この逆のことがおこります。スクロールによって要素の選択状態が変わることはありません。
リスト内の要素をタップすると、選択されている要素のハイライトが解除され、タップされた要素がハイライト表示されます。リスト上でペンをドラッグするとペンの下にある要素がハイライト表示されます。リストの境界よりも上または下までペンをドラッグすると、スクロールによって表示できる要素があればリストをスクロールします。
ペンを要素上から離すと、その要素が現在の選択要素になります。ペンをリストの外側までドラッグした場合、penDownEvent を処理する直前までハイライトされていた要素がリスト内に表示されていれば再びハイライトされます。それ以外の場合、どの要素もハイライト表示されません。
アプリケーションはリストを2つの方法で使うことができます。
- リストの全要素のデータを含む構造体を初期化し、リスト自身にデータを管理させる。
- メモリ上にはデータを保持せず、リストを描画する関数を用意する。リストは描画のたびにデータを取得します。メモリにデータを保持しないことにより、リストが長大かつその内容がユーザー操作に依存する場合に発生する容認し難いメモリのオーバーヘッドを避けることができます。例として、ユーザーが選択した都市を基準にして多くの都市の時刻一覧を表示するような時刻変換アプリケーションが考えられます。このような実行時の表示情報取得ができるのはリストだけで、テーブルではできないことに注意して下さい。
訳注:customTableItem を使用したカスタム描画を使えばテーブルでも 同じようなことができるような気がしますが、この文が言おうと していることは違うのでしょうか。訳が良くないかもしれません。
LstHandleEvent 関数はリストのイベントを処理します。表 4.16 に LstHandleEvent が各種のイベントをどのように扱うかの概要を示します。
表 4.16 リストのイベントフロー
ユーザー操作 | システムの応答 | LstHandleEvent の応答 |
---|---|---|
ポップアップトリガーのボタンをペンで押下 | リストのウィンドウを識別する winEnterEvent | lstEnterEvent をイベントキューに追加 |
リストの ID と選択要素を格納した lstEnterEvent | ペンを追跡 | |
リストボックスをペンで押下 | penDownEvent と x & y 座標を EventType に設定 | ペンの下にある要素をハイライト |
ペンをリストボックスから離す | penUpEvent と x & y 座標を EventType に設定 | lstSelectEvent をイベントキューに追加 |
リストの ID と選択要素を格納した lstSelectEvent | 新し選択を保存。リストがポップアップトリガーに関連付けられている場合、ポップアップトリガー ID、ポップアップリスト ID、および EventType で選択された要素番号を格納した popSelectEvent をイベントキューに追加。コントロールを FrmHandleEvent に渡す。 | |
ペンをリストボックスの外側で離す | penUpEvent と x & y 座標を EventType に設定 | winExitEvent をイベントキューに追加 |
テーブルのかわりにリストを使用する
リストは単一の列のテキスト行で構成されますが、カスタム描画関数を使用して複数列表示を模倣することは可能です。多くのプログラマは複数列の表示をしたい場合にテーブルではなくリストを選択します。それは、リストが一般にテーブルよりもプログラミングが簡単だからです。しかし、それにはいくつかの問題もあります。というのは、リストオブジェクトには常に周囲に矩形の境界線が表示されるからです。テーブルが通常表示するような複数列データを表示するためにリストを使うのであれば、リストの境界線が描画されるのを抑止しなければなりません。そのための安全な方法は、リスト 4.2 に示すようにリストが描画される前のリストの領域をクリッピングした矩形を描画することです。詳細は「 Palm OS User Interface Guidelines 」を参照して下さい。
リスト 4.2 リストの境界線の抑止
void DrawFormWithNoListBorder(FormType *frmP, UInt16 listIndex) { RectangleType *clip; RectangleType *newClip; ListType *listP = FrmGetObjectPtr(frmP, listIndex); // Hide the list object and then draw the rest of the form. FrmHideObject(frmP, listIndex); FrmDrawForm (frmP); // Set the clipping rectangle to the list boundaries and // draw the list. This suppreses the list border. WinGetClip(&clip); FrmGetObjectBounds(frmP, listIndex, &newClip); WinSetClip(&newClip); LstSetSelection(listP, noListSelection); FrmShowObject(frmP, listIndex); // Reset the clipping rectangle. WinSetClip(&clip); } Boolean MyFormHandleEvent(EventPtr eventP) { Boolean handled = false; FormType *frmP; UInt16 listIndex; switch (eventP->eType) { case frmOpenEvent: frmP = FrmGetActiveForm(); listIndex = FrmGetObjectIndex(frmP, MyListRscID); // initialize form here. DrawFormWithNoListBorder(frmP, listIndex); handled = true; break; case frmUpdateEvent: frmP = FrmGetActiveForm(); listIndex = FrmGetObjectIndex(frmP, MyListRscID); DrawFormWithNoListBorder(frmP, listIndex); handled = true; break; ... } }