Oracle Applications開発者ガイド リリース12 E06048-01 | 目次 | 前へ | 次へ |
ウィンドウの動作の制御には、ウィンドウが開くときの位置を指定するコーディング・ロジック、どのような条件でどのウィンドウが閉じるかの制御、詳細ウィンドウへのコンテキスト依存のタイトル付与などが含まれます。個々のウィンドウのブロック間にマスター詳細関連が存在する場合は、その状況に応じたロジックもコーディングする必要があります。
関連項目: マスター詳細関連のコーディング
例
「発注」ヘッダー・ウィンドウに、「明細」というラベルのボタンがあり、他のウィンドウのLINESブロックへ移動できるようにする場合を考えます。
次のトリガーを追加または変更します。
トリガー: PRE-FORM:
app_window.set_window_position('HEADER','FIRST_WINDOW');
トリガー: 「LINES」ボタンでWHEN-BUTTON-PRESSED:
app_custom.open_window('LINES');
APP_CUSTOM.OPEN_WINDOWを次のように修正します。
IF wnd = 'LINES' THEN
APP_WINDOW.SET_WINDOW_POSITION('LINES',
'CASCADE','HEADER');
go_block('LINES');
END IF;
使用可能なスタイルは次のとおりです。
CASCADE: 子ウィンドウが、親ウィンドウの現在の位置から0.3インチ右下に、親ウィンドウに重なって表示されます。通常、詳細ウィンドウに使用します。
RIGHT, BELOW: 子ウィンドウが、親ウィンドウには重ならずに、右側または下に開きます。
OVERLAP: 詳細ウィンドウが、親ウィンドウより0.3インチ下に(左揃え)、親ウィンドウと重なって表示されます。
CENTER: ウィンドウが他のウィンドウの間で真ん中に表示されます。通常、モーダル・ウィンドウに使用します。
FIRST_WINDOW: ウィンドウがツールバーの直下に表示されます。通常、メイン・エンティティ・ウィンドウに使用されます。
非モーダル・ウィンドウ(モーダル・ウィンドウ以外)を閉じるイベントは、すべてAPP_CUSTOM.CLOSE_WINDOWへ渡されます。TEMPLATEフォームで提供されるデフォルト・コードは次のとおりです。
このフォームが問合せ入力モードの場合、APP_CUSTOMは次をコールします。
APP_EXCEPTION.DISABLED
あるいは、閉じるウィンドウ内に現在カーソルがある場合、APP_CUSTOMはdo_key('PREVIOUS_BLOCK')を使用してカーソルを現在のウィンドウの外へ移動します。
最後に、APP_CUSTOMはHIDE_WINDOW('<window_name>')をコールしてウィンドウを非表示にします。
他の動作に対応するためには、このプロシージャを修正する必要があります。具体的には、ブロック調整機能と詳細ウィンドウを処理するように修正します。
ウィンドウを閉じる前に、カーソルを外に移動させる必要があることに注意してください。そうしない場合、再びウィンドウが自動的に開くことになります。
フォームの最初のウィンドウを閉じるには(「ファイル」->「フォームのクローズ」と同等)、APP_WINDOW.CLOSE_FIRST_WINDOWをコールします。
例
「ヘッダー」、「明細」および「出荷」ウィンドウがあるフォームで(ここで「明細」は「ヘッダー」の詳細、「出荷」は「明細」の詳細)、ウィンドウを閉じるロジックは次のようになります。
PROCEDURE close_window (wnd VARCHAR2) IS
IF wnd = 'HEADER' THEN
--
-- Exit the form
--
app_window.close_first_window;
ELSIF wnd = 'LINES' THEN
--
-- Close detail windows (Shipments)
--
app_custom.close_window('SHIPMENTS');
--
-- If cursor is in this window,
-- move it to the HEADER block
--
IF (wnd = GET_VIEW_PROPERTY(GET_ITEM_PROPERTY(
:SYSTEM.CURSOR_ITEM,ITEM_CANVAS),
WINDOW_NAME)) THEN
GO_BLOCK('HEADER');
END IF;
ELSIF wnd = 'SHIPMENTS' THEN
--
-- If cursor is in this window,
-- move it to the LINES block
--
IF (wnd = GET_VIEW_PROPERTY(GET_ITEM_PROPERTY(
:SYSTEM.CURSOR_ITEM, ITEM_CANVAS),
WINDOW_NAME)) THEN
GO_BLOCK('LINES');
END IF;
END IF;
--
-- THIS CODE MUST REMAIN HERE. It ensures
-- the cursor is not in the window that will
-- be closed by moving it to the previous block.
--
IF (wnd = GET_VIEW_PROPERTY(GET_ITEM_PROPERTY(
:SYSTEM.CURSOR_ITEM, ITEM_CANVAS),
WINDOW_NAME)) THEN
DO_KEY('PREVIOUS_BLOCK');
END IF;
--
-- Now actually close the designated window
--
HIDE_WINDOW(wnd);
END close_window;
警告: カーソルを移動し、このプロシージャに渡されるウィンドウ名を閉じるデフォルト句は残しておく必要があります。
関連項目: マスター詳細関連のコーディング
警告: ウィンドウ・タイトルには、丸括弧またはコロン(「(」または「:」)を含めないでください。これらの文字は、タイトルを動的に変更してコンテキストを表示する際に、APPCOREウィンドウのタイトル・ルーチンにより追加されます。ベース・ウィンドウ・タイトルに、これらの文字が含まれることはありません。ハイフン(-)を使用する場合、スペースでハイフンを囲まないでください。つまり、ハイフンの前後にスペースを入れることはできません。
動的タイトルの例
「仕訳データの入力」フォームで、「仕訳明細」ウィンドウに現在の「会計帳簿」および「仕訳」名を表示する場合を考えます。
Oracle Forms Developerで、「明細」ウィンドウのタイトルを、「仕訳明細」に設定します。
「仕訳」ブロックのPRE-RECORDトリガーを次のようにコーディングします。
app_window.set_title('LINES', name_in('Journal.SOB'),
:journal.name);
journal.namesフィールドのWHEN-VALIDATE-ITEMトリガーを次のようにコーディングします。
app_window.set_title('LINES', name_in('Journal.SOB'),
:journal.name);
ウィンドウのベース・タイトルを変更する必要がある場合には、SET_WINDOW_ PROPERTY(...TITLE...)をコールします。それ以降APP_WINDOW.SET_ TITLEがコールされる際は常に、新しいベース・タイトルが保持されます。
ブロックの動作の制御は、マスター詳細関連のコーディングと組合せブロックの実装を含みます。
関連項目: マスター詳細関連のコーディングおよび組合せブロックの実装
詳細ブロックがそのマスターとは別のウィンドウにあり、各ウィンドウが非モーダルである場合、詳細ブロックにはユーザーが即時調整と遅延調整を切り替えることのできる手段が必要です。これにより、ユーザーはブロックを表示したまま、マスター・レコードが変更されたときに詳細レコード調整のパフォーマンス・コストを制御できるようになります。
詳細ブロックが非表示の場合、その調整は常に遅延である必要があります。プロシージャAPP_WINDOW.SET_COORDINATIONを使用して、異なるウィンドウのマスター詳細ブロックを調整します。
関連項目: APP_WINDOW: ウィンドウ・ユーティリティ
サンプル・コードでは次のオブジェクトを使用します。
ウィンドウORDERSの、マスター・ブロックORDERS
ウィンドウLINESの、詳細ブロックLINES
関連ORDERS_LINES
「調整」チェック・ボックスCONTROL.ORDERS_LINES
LINESブロックのCONTROL.LINESへナビゲートするボタン
詳細ブロックへナビゲートするボタンを作成します。
詳細ウィンドウの制御ブロックで「調整」チェック・ボックスを作成し、ウィンドウが開くときの即時調整または遅延調整のユーザー作業環境を設定します。チェック・ボックスにはCHECKBOX_COORDINATIONプロパティ・クラスが必要であり、選択した場合は「IMMEDIATE」の値に、選択を解除した場合は「DEFERRED」の値になります。チェック・ボックス値のデフォルトは、選択した状態(IMMEDIATE)です。
項目ハンドラ・プロシージャを次のように作成します。
PACKAGE BODY control IS
PROCEDURE lines(EVENT VARCHAR2) IS
BEGIN
IF (EVENT = 'WHEN-BUTTON-PRESSED') THEN
app_custom.open_window('LINES');
END IF;
END lines;
PROCEDURE orders_lines(EVENT VARCHAR2) IS
BEGIN
IF (EVENT = 'WHEN-CHECKBOX-CHANGED') THEN
APP_WINDOW.SET_COORDINATION(EVENT,
:control.orders_lines,
'ORDERS_LINES');
END IF;
END orders_lines;
END control;
次のように、APP_CUSTOMテンプレート・パッケージをカスタマイズします。
OPEN_WINDOWプロシージャに、次を追加します。
IF (WND = 'LINES') THEN
APP_WINDOW.SET_COORDINATION('OPEN-WINDOW',
:control.orders_lines,
'ORDERS_LINES');
GO_BLOCK('LINES');
END IF;
CLOSE_WINDOWプロシージャに、次を追加します。
IF (WND = 'LINES') THEN
APP_WINDOW.SET_COORDINATION('WHEN-WINDOW-CLOSED',
:control.orders_lines,
'ORDERS_LINES');
END IF;
次の方法で、フィールドおよびイベント・ハンドラ・プロシージャをコールします。
トリガー: control.linesのWHEN-BUTTON-PRESSED:
control.lines('WHEN-BUTTON-PRESSED');
トリガー: ORDERのKEY-NXTBLK:
control.lines('WHEN-BUTTON-PRESSED');
トリガー: control.order_linesのWHEN-CHECKBOX-CHANGED:
control.orders_lines('WHEN-CHECKBOX-CHANGED');
ブロック内の項目ごとに、それぞれ「表示項目数」プロパティを設定できるので、1つのブロックにシングル・レコード(「詳細」)である項目と、マルチ・レコード(「要約」)を含めることができます。組合せブロックを実装する場合ほとんどの項目が2度出てくるため、そのような項目の値の調整を管理する必要があります。「項目と同期」プロパティによって、これを自動的に行います。「スイッチャ」と呼ばれるフィールドを使用して、様々な状況でブロックのどの部分にナビゲートするかを制御します。「スイッチャ」フィールドは、ブロックの中で最初にナビゲート可能な項目です。カーソルが「スイッチャ」に入ると、ブロックの各「詳細」または「要約」部分の最初の項目へただちに移動します。
組合せブロックの設定
2つのウィンドウおよびキャンバスを作成して、異なるブロック部分を保持します。「要約」部分には、ブロックの非ミラー項目を使用します。項目を複製し、「詳細」部分を作成します。組合せブロックの「詳細」部分は、順番の最初に配置します。したがって、ユーザーが必要な項目に記入せずにコミットする場合、Oracle Formsがカーソルを「詳細」ブロックのその項目に移動します。
項目プロパティの設定
ミラー項目に対して、項目名を変更してミラー元の実際の項目に反映します(たとえば、「status」のミラー項目名を「status_mir」にします)。「項目と同期」プロパティを設定し、「データベース項目」プロパティが「Yes」に設定されていることを確認してください(同期化項目が、実表の項目である場合)。
「要約」にあるブロック・レベルの「表示項目数」プロパティを設定します。これは、「表示項目数」プロパティを明示的に設定していなければ、項目により使用されます。「詳細」部分の項目は同じ値を取得しないので、「表示項目数」プロパティを明示的に1に設定します。
ユーザーが「詳細」から「要約」へタブを移動するのを避けるため、最初の「詳細」項目に「前ナビゲーション項目」プロパティを、最後の「詳細」項目に「次ナビゲーション項目」プロパティを設定します。
「レコードの変更」の標準マルチ・レコード・ブロックのナビゲーション動作を規定するため、「要約」部分にある最初のナビゲート可能項目のKEY-PREV-ITEMトリガー(問合せ入力モードではない場合に起動)でAPP_COMBO.KEY_PREV_ITEMをコールし、「要約」部分にある最後のナビゲート可能項目のKEY-NEXT-ITEMトリガー(問合せ入力モードではない場合に起動)でnext_recordをコールします。
既存のブロックを組合せブロックに変換する場合、すべての既存のトリガーにおける参照が、すべてのフィールドに2つのインスタンスが存在することを認識するように忘れずに変更してください。
関連項目: APP_COMBO: 組合せブロックAPI
ドリルダウン・レコード・インディケータ
execute_trigger('SUMMARY_DETAIL')を実行するドリルダウン・レコード・インディケータを追加します。
レコード・カウント・パラメータ
パラメータを作成して、現在のブロックの部分のレコード・カウンタを保存します。パラメータ名は<block>_RECORD_COUNTとします。ここで、<block>は、組合せブロックの名前です。APPCOREコードは、このネーミング標準により決まります。この情報を利用して、ブロックのどの部分をナビゲートするかを決定します。最初にカーソルを「要約」に配置するには、パラメータにはNUMBERというデータ型が必要で、デフォルト値を2にします。(最初のカーソルの位置を「詳細」部分にする場合、デフォルト値を1に設定します。)
次のコードを含む、ブロック・レベルのWHEN-NEW-ITEM-INSTANCEトリガー(実行階層は「前」)を作成します。
:PARAMETER.<block>_RECORD_COUNT :=
GET_ITEM_PROPERTY(:SYSTEM.CURSOR_ITEM,
RECORDS_DISPLAYED);
スイッチャ
テキスト項目を作成し、プロパティ・クラスSWITCHERに割り当てます。これは、ブロックの順番の一番下にする必要があります。ツールバー・キャンバスの(0,0)に配置します。(スイッチャは配置されたキャンバスの色になるので、ツールバー・キャンバスに置く必要があります)。次のコードを含む、項目レベルのWHEN-NEW-ITEM-INSTANCEトリガー(実行階層は「オーバーライド」)を作成します。
IF(:PARAMETER.<block>_RECORD_COUNT > 1) THEN
GO_ITEM('<first Summary field>');
ELSE
APP_WINDOW.SET_WINDOW_POSITION('<Detail window>',
'OVERLAP',
'<Summary window>');
GO_ITEM('<first Detail field>');
END IF;
「要約/詳細」メニュー項目
次のコードを含む、ブロック・レベルのSUMMARY_DETAILトリガー(実行階層は「オーバーライド」)を作成します。
IF GET_ITEM_PROPERTY(:SYSTEM.CURSOR_ITEM,
RECORDS_DISPLAYED) > 1 THEN
:PARAMETER.<block>_RECORD_COUNT := 1;
ELSE
:PARAMETER.<block>_RECORD_COUNT := 2;
END IF;
GO_ITEM('<block>.Switcher');
このコードにより、RECORDS_DISPLAYEDパラメータ内の値が変更され、スイッチャはブロックの反対側の部分にカーソルを送ります。これは、ユーザーが「実行」->「要約/詳細」を選択したときに必ず起動されます。
次のコードを含む、ブロック・レベルのPRE-BLOCKトリガー(実行階層は「オーバーライド」)を作成します。
APP_SPECIAL.ENABLE('SUMMARY_DETAIL', PROPERTY_ON);
最後に、次のコードを含むフォーム・レベルのPRE-BLOCKトリガー(実行階層は「オーバーライド」)を作成します。
APP_SPECIAL.ENABLE('SUMMARY_DETAIL', PROPERTY_OFF);
すべてのブロックが組合せブロックである場合、SUMMARY_DETAILをフォーム・レベルで有効にし、PRE-BLOCKトリガーを無視できます。大部分のブロックが組合せブロックの場合は、SUMMARY_DETAILをフォーム・レベルで有効にし、組合せブロックではないブロックについてはブロック・レベルで無効にします。
初期ナビゲーションおよびウィンドウ操作
組合せブロックが、フォームの最初のブロックである場合、次のコールにより2つのウィンドウをPRE-FORMトリガーに配置します。
APP_WINDOW.SET_WINDOW_POSITION('<Summary window>',
'FIRST_WINDOW');
APP_WINDOW.SET_WINDOW_POSITION('<Detail window>',
'OVERLAP',
'<Summary window>');
通常、「要約」が先に入力されますが、「詳細」が先に入力されることが動的に決定される場合があります。動的に決定する必要がある場合、PRE-FORMトリガーのパラメータ<block>_RECORD_COUNTを設定します(「詳細」に送るには1、「要約」に送るには2)。
タブ・リージョンとは、関連するタブが1つのグループとなったウィンドウの領域のことです。関連するタブのグループおよびそれに対応するタブ・ページが、タブ・リージョンを構成していると考えられます。Forms Developerでは、タブ・キャンバスと呼んでいます。各タブ・キャンバスは、1つ以上のタブ・ページから構成されています。
タブ・ページは、ウィンドウの領域およびフィールド(項目)の関連するグループで、ユーザーが「タブ」図形要素をクリックしたときに表示されます。「タブ」という用語は、多くの場合「タブ・ページ」という用語と同様に使用できます。Form Builderでは、タブ・ページは実際に利用する画面のことです。Form Builderは、タブ・ページのサイズをタブ・キャンバス・ビューポートに収まるように自動調整します。
一番手前のタブ・ページとは、現在「上」に位置している、つまり現在選択され、表示されているタブ・ページのことです。
固定フィールドは、特定のタブ・リージョンにある複数またはすべてのタブ・ページに表示されているフィールドおよび項目です。固定フィールドには、コンテキスト・フィールドと主キー・フィールドのいずれかまたは両方、ブロック・スクロールバー、現行のレコード・インディケータまたはドリルダウン・インディケータ、付加フレックスフィールドが含まれる場合があります。
代替リージョン・フィールド(一意のタブ・ページ・フィールド)は、1つのタブ・ページに対して一意なフィールドで、したがってタブ・リージョンの別のタブ・ページには表示されません。代替リージョン・フィールドは固定フィールドとは対照的に、1つのタブ・リージョンにある複数またはすべてのタブ・ページに表示されることはありません。
「制御」は、フィールド、項目またはウィジェットに対して使用する別の用語です。テキスト項目、表示項目、チェック・ボックス、スクロール・バー、ボタン、オプション・グループなどが含まれます。
タブ・リージョンによって、Oracle Applicationsはタブ・ページを表示し、どのタブがクリックされたかによって適切なフィールドにフォーカスを置くことができます。Oracle Formsにおける基本的な動作とは、ユーザーがタブをクリックしたときにタブ・ウィジェットにフォーカスを置くことであり、コードを作成してこの動作を実現する必要があります。
Oracle Formsで「カーソル・フォーカス」という用語は、「マウス・フォーカス」あるいはよりシンプルに「フォーカス」と同じ意味です。
ユーザーは、キーボードからタブに直接アクセスできます。定義可能なホット・キーを使用して、利用可能なタブのリストにアクセスします(デフォルトでは[F2]キー)。
さらに、ユーザーは「次フィールド」や「前フィールド」をクリックすることにより、必要に応じてブロックのすべてのフィールド、およびタブ・ページ間を移動できます。選択したタブは、表示されているフィールドの現在のグループと常に同期されている必要があります。多くのタブ・リージョンが、直接タブ・ページにフィールドを配置するのではなく、スタック・キャンバスを使用してフィールドを保持しているため、タブがスタックされたキャンバスと常に同期されるようコーディングする必要があります。
フォーム・セッション中にタブを適用しない場合は、起動時にタブを非表示にします。フォーム・セッション中にタブの非表示および表示を切り替えないでください。お薦めはできませんが、タブを1つ表示させたままにしておくことが可能です。各レコード内のデータによって状態が決まる場合は、動的にタブの非表示および表示を切り替えます。
タブは、問合せ入力モードで操作します。問合せ入力モードでgo_itemコールにより移動するフィールドは、問合せ可能である必要があります。タブ・ページ内でキャンバス・スクロールを必要とするフォームもあります。
これらの動作は、後続の項で説明するとおり、タブ・リージョンのハンドラを特定の方法でコーディングすることによって実現します。
3段階の難易度があり、それぞれ異なるレイアウト方法およびコーディング方法が要求されます。
基本:スクロールなし、固定フィールドなし
標準:スクロールあり、固定フィールドなし
高度: 固定フィールドあり、スクロールは任意
レイアウト方法の違いには、スタック・キャンバスを使用するかどうか、およびいくつ使用するかといったことが含まれます。そして、コーディング方法の違いには、スタック・キャンバスを使用したタブの動作の処理に必要な追加のコードが含まれます。
基本的なケースには、異なるページでフィールドが繰り返されることのない単一行タブ・ページが含まれます。通常、これらはフォームの独立したブロックになっています。
タブ・ページにつき1つのブロックがあり、それぞれに独立したブロック・スクロールバーがあるが、フィールドの水平スクロールはできないタブ・リージョンのように、複数の独立した複数行ブロックを伴うフォームがある場合、同様に基本的なケースとしてコーディングできます。たとえば、システム管理者職責における「ユーザー」ウィンドウは、基本的なケースに該当します。
基本的なケースでは、項目を直接タブ・ページに配置します。基本的なケースにスタック・キャンバスは必要ありません。
標準的なケースには、異なるページでフィールドが繰り返されることのない単一行タブ・ページが含まれますが、タブ・ページ内の全ページにアクセスできるスクロールバーが必要です。通常、これらのタブ・ページは、フォームの独立したブロックになっています。
タブ・ページにつき1つのブロックで、それぞれに独立したブロック・スクロールバーがあり、フィールドの水平スクロールが可能なタブ・リージョンのように、複数の独立した複数行ブロックを伴うフォームがある場合、同様に標準的なケースとしてコーディングできます。ブロック・スクロールバーおよびボタンのような「固定」(ただし共有されない)オブジェクトは、このケースのタブ・ページに直接配置できます。
標準的なケースでは、項目をタブ・ページの手前のスタック・キャンバスに配置して、フィールドのスクロールを容易にできます。
高度なケースでは、様々なタブ・ページ間で共有される固定フィールドを処理できます。このケースには、複数のタブ・ページにまたがる複数行ブロックが含まれます。通常、固定フィールドにはコンテキスト・フィールド、現行またはドリルダウンのレコード・インディケータ、記述フレックスフィールド、およびブロック・スクロールバーが含まれます。
フレックスフィールドの場合は、項目をタブ・ページの手前のスタック・キャンバスに配置して、フィールドのスクロールを容易にできます。フレックスフィールドには特別なスタック・キャンバスが必要で、タブ・ハンドラにコードを追加する必要があります。
タブ・リージョンの実装は、基本的に主要な2つの段階からなっています。
Forms Developerでのレイアウトの作成
タブ・ハンドラのコーディング
次の手順で、Oracle Applicationsの標準に基づいたタブ・リージョンの実装方法を説明します。これらの手順は、各手順で説明されているような違いはありますが、3つのケース(基本、標準、高度)のすべてに適用されます。
関連項目: Forms Developerでのレイアウトの作成
Forms Developerでレイアウトを作成する手順を次に示します。
タブ・キャンバスを作成します。タブ・キャンバスに、標準形式TAB_ENTITY_REGIONS(ENTITYはLINESなどのエンティティ)または同様の名前を付けます。たとえば、タブ・キャンバスの名前はTAB_LINES_REGIONSのようにできます。TAB_CANVASプロパティ・クラスを適用します。
タブ・キャンバスのウィンドウ・プロパティを設定すると、タブ・キャンバスが適切なウィンドウに表示されます。タブ・キャンバスのウィンドウ・プロパティを適切なウィンドウに設定しない場合、Form Builderで「ビュー」->「スタック・ビュー」メニューを選択してコンテンツ・キャンバスにタブ・キャンバスは表示できません。
タブ・キャンバスを調整します。キャンバスの順序をコンテンツ・キャンバスの後、および手前に表示されるすべてのスタック・キャンバスより前に置きます。Layout Editorでそのビューポートを調整します。同時にコンテンツ・キャンバスを表示すると、タブ・キャンバスの位置をうまく調整できます。
タブ・ページを作成します。
標準および高度なケースの場合、タブ・ページの名前は対応する「代替リージョン」スタック・キャンバスの名前と一致している必要があります。
タブ・ページを調整します。各タブ・ページにプロパティ・クラスTAB_PAGEを適用し、タブ・ページ・ラベルを設定します。Object Navigatorのタブ・ページの順序を、項目タブの順序に一致するように指定します。
高度なケースの場合のみ、固定フィールド・スタック・キャンバスを作成し、その名前を(tab_canvas)_FIXEDとします。順序を、タブ・キャンバスの後、かつ高度なケースで作成するすべての「代替リージョン」スタック・キャンバスの前に置きます。プロパティ・クラスCANVAS_STACKED_FIXED_FIELDを適用します。フレックスフィールド・キャンバス・ビューポートを、ちょうどタブ・キャンバス・ビューレポートの内側に収まるように設定します。
標準および高度なケースの場合のみ、「代替リージョン」スタック・キャンバスを作成します。これらのキャンバスは、ビューポートのサイズと位置をすべて同じにする必要があります。代替リージョン・スタック・キャンバスの「可視」プロパティを確認します(最初のキャンバスのみを表示する場合「Yes」に設定します)。
高度なケースの場合、これらの「代替リージョン」キャンバスにより固定フィールド・キャンバスの一部(すべてではありません)が隠れてしまいます。ビューポートの位置とサイズが、固定フィールド・キャンバスに対して適切な位置に設定されているかどうかを確認してください。
項目を適切なタブ・ページまたはスタック・キャンバスに配置します。ブロック・スクロールバーがある場合、キャンバスの右端に配置します。
スタック・キャンバスを使用している場合、スタック・キャンバスはタブ・ページに直接配置されているフィールドをオーバーラップしない点に注意してください。同様に、どの「代替リージョン」スタック・キャンバスも、固定フィールド・スタック・キャンバスの項目をオーバーラップすることはありません。
レイアウトを調整します。フィールド・プロンプトを、フィールドのプロパティのように適宜設定します。
タブ・リージョンのレイアウトを設定する際の注意: タブ・リージョンのフィールドおよび他の要素のレイアウトを設定する際の根本的な基準は、見た目が美しいという点です。これには、タブ・ページの内側および外側に十分なスペースを残して、過度に雑然としたレイアウトにしないということが含まれます。この点を満たすために必要なレイアウト設定は、1通りではありません。たとえば、タブ・リージョンの最後にある複数行チェック・ボックスの場合、テキスト項目を同じ場所に配置する場合よりも、タブ・ページの端との間に多くの空白が必要な場合があります。
Forms DeveloperのLayout Editorでは、タブおよびスタック・キャンバスにOracleルック・アンド・フィールを利用できない点にも注意してください。Oracleルック・アンド・フィールは、実行時のみ利用できます。設計時には、見た目ではなくビューポートの数値を使用する必要があります。
詳細は、『Oracle Applicationsフォーム・ベース製品のユーザー・インタフェース標準』を参照してください。
タブ・リージョンの実装における2番目の段階であるタブ・ハンドラのコーディング手順を次に示します。
タブ・ハンドラをコーディングします。次の2つのテンプレート・ファイルが用意されており、簡単にハンドラをコーディングできます。
FNDTABS.txt(基本的および標準的なケース)
FNDTABFF.txt(固定フィールドのケース)
FNDTABS.txtおよびFNDTABFF.txtの場所は、FND_TOP/resource(ファイル名は小文字の場合があります)の下です。適切なタブ・ハンドラのテンプレート・ファイルを選択してください(FNDTABS.txtまたはFNDTABFF.txt)。フォーム(通常ブロック・パッケージまたは制御パッケージ内にあります)またはライブラリにハンドラ・テキストをインポートし、フォームに合うように変更します。フォーム・オブジェクト名にあわせ、特に必要な動作を実行するように変更します。ファイルには多くのコメントが含まれており、ファイルの変更を適切な部分に行うのに役立ちます。
トリガーからタブ・ハンドラをコールします。フォーム・レベルのWHEN-TAB-PAGE-CHANGEDトリガーを追加し、新規ハンドラをコールします。トリガーは、WHEN-TAB-PAGE-CHANGEDイベントをハンドラに渡します。たとえば、次のとおりです。
MY_PACKAGE.TAB_MY_ENTITY_REGIONS('WHEN-TAB-PAGE-CHANGED');
WHEN–NEW–ITEM–INSTANCEトリガーをコーディングし、新規ハンドラをコールします。通常、このトリガーはブロック・レベルでコーディングします(実行階層スタイルは「前」)。たとえば、次のとおりです。
MY_PACKAGE.TAB_MY_ENTITY_REGIONS('WHEN-NEW-ITEM-INSTANCE');
通常、タブ・ハンドラは次のトリガーからのコールを受け入れます。
WHEN-TAB-PAGE-CHANGED
WHEN-NEW-ITEM-INSTANCE
KEY-CLRFRMなど、適切な他のトリガー
タブ・ハンドラには、これらのイベントごとにブランチがあります。
ユーザーがタブを押すと、WHEN-TAB-PAGE-CHANGEDロジックにより次の動作が実行されます。
現在のフィールドの検証
適切なフィールドへのカーソルの移動
スタック・キャンバスの明示的な表示(必要な場合)
WHEN-TAB-PAGE-CHANGEDトリガーは、ユーザーがタブをクリックした場合のみ起動します。プログラムにより起動させることはできず、フォーム・レベルでのみ使用できます。
次に示すのは、FNDTABS.txtファイルのWHEN-TAB-PAGE-CHANGEDブランチです(基本的および標準的なケース)。
IF (event = 'WHEN-TAB-PAGE-CHANGED') THEN
if name_in('system.cursor_block') = 'MY_BLOCKNAME' then
validate(item_scope);
if not form_success then
-- Revert tab to prior value and exit
set_canvas_property('TAB_ENTITY_REGIONS',
topmost_tab_page,
name_in('system.tab_previous_page'));
return;
end if;
-- Move to first item on each tab
if target_canvas_name = 'MY_FIRST_TAB_PAGE' then
go_item('MY_BLOCKNAME.FIRST_TAB_PAGE_FIRST_FIELD');
elsif target_canvas_name = 'MY_SECOND_TAB_PAGE' then
go_item('MY_BLOCKNAME.SECOND_TAB_PAGE_FIRST_FIELD');
elsif target_canvas_name = 'MY_THIRD_TAB_PAGE' then
go_item('MY_BLOCKNAME.THIRD_TAB_PAGE_FIRST_FIELD');
end if;
else
show_view(target_canvas_name);
end if;
次に示すのは、FNDTABFF.txtファイルのWHEN-TAB-PAGE-CHANGEDブランチです(固定フィールドのケース)。
IF (event = 'WHEN-TAB-PAGE-CHANGED') THEN
if name_in('system.cursor_block') = 'MY_BLOCKNAME' then
-- Process the 'First' tab specially. If the
-- cursor is already on a field on the
-- 'Fixed' canvas then we merely show the other
-- stacked canvas; otherwise, we move the cursor
-- to the first item on it.
if target_canvas_name =
'MY_FIRST_ALT_REG_CANVAS' then
if curr_canvas_name =
'TAB_ENTITY_REGIONS_FIXED' then
show_view(target_canvas_name);
go_item(name_in('system.cursor_item');
-- move focus off the tab itself
else
validate(item_scope);
if not form_success then
-- Revert tab to prior value and exit
set_canvas_property('TAB_ENTITY_REGIONS',
topmost_tab_page,
name_in('system.tab_previous_page'));
return;
end if;
show_view('MY_FIRST_ALT_REG_CANVAS');
-- display first stacked canvas
go_item(
'MY_BLOCKNAME.FIRST_ALT_REG_FIRST_FIELD');
-- go to first item on that stacked canvas
end if;
else
validate(item_scope);
if not form_success then
-- Revert tab to prior value and exit
set_canvas_property('TAB_ENTITY_REGIONS',
topmost_tab_page,
name_in('system.tab_previous_page'));
return;
end if;
--
-- Move to first item on each additional
-- (non-first) tab
--
if target_canvas_name =
'MY_SECOND_ALT_REG_CANVAS' then
go_item(
'MY_BLOCKNAME.SECOND_ALT_REG_FIRST_FIELD');
elsif target_canvas_name =
'MY_THIRD_ALT_REG_CANVAS' then
go_item(
'MY_BLOCKNAME.THIRD_ALT_REG_FIRST_FIELD');
end if;
end if;
else
show_view(target_canvas_name);
end if;
次の変数は、WHEN-TAB-PAGE-CHANGEDトリガー(またはこのトリガーによりコールされるコード)内でのみ有効です。
:SYSTEM.TAB_NEW_PAGEは、ユーザーがクリックしたタブ・ページの名前です。
:SYSTEM.EVENT_CANVASは、新しく選択したタブ・ページが存在するキャンバスの名前です。
:SYSTEM.TAB_PREVIOUS_PAGEは、ユーザーが新しいタブをクリックする前、一番手前に表示されていたタブ・ページの名前です。
妥当性チェックは、次の行を含むハンドラの一部です。
validate(item_scope);
これに、妥当性チェックが失敗した場合にタブを元の値にリセットするコードが続きます。
チェック・ルーチンがコールされると、ユーザーがフィールドの外にタブ移動した場合と同様に、現行フィールドの妥当性チェックが強制されます。この妥当性チェックには、有効な値(データ型、値の範囲など)を含むフィールドのチェックと、項目に適用可能なすべてのWHEN-VALIDATE-ITEMロジックの起動が含まれます。妥当性チェックが必要なのは、ユーザーがタブをクリックするとただちにWHEN-TAB-PAGE-CHANGEDトリガーが起動するためです(ユーザーがタブをクリックする前にいたフィールドのWHEN-VALIDATE-ITEMトリガーは、WHEN-TAB-PAGE-CHANGEDトリガーより前に起動することはありません)。
フォームを問合せのみに使用する場合、妥当性チェックは必要なく、タブ・ハンドラから削除できます。
タブ・リージョンに問合せ可能でないフィールドがある場合、状況によってはロジックを調整して問合せ入力モードでの操作を許可する必要があります。すべてのgo_itemコールが問合せ可能フィールドに移動しているはずなので、ユーザーが問合せ入力モードになっているかどうかをテストして適切なフィールドに移動する必要があります。
問合せ入力モードでのテストは次のように行います。
IF :system.mode = 'ENTER-QUERY' THEN ...
フォームに、タブ・セットが1つしかない場合、タブ・ハンドラをフォーム・レベルのWHEN-TAB-PAGE-CHANGEDトリガーからコールし、次のようにWHEN-TAB-PAGE-CHANGEDイベントに渡します。
my_package.tab_my_entity_regions('WHEN-TAB-PAGE-CHANGED');
複数のタブ・セット(複数のタブ・リージョン)がある場合、タブ・リージョンごとに独立したタブ・ハンドラが必要です。この場合、フォーム・レベルのWHEN-TAB-PAGE-CHANGEDトリガーは、現行キャンバス名でブランチして適切なタブ・ハンドラをコールする必要があります。このブランチ処理は、フォームに複数のタブ・キャンバスがある場合にのみ必要です。たとえば、次のとおりです。
declare
the_canvas varchar2(30) := :system.event_canvas;
begin
if the_canvas = 'FIRST_TAB_REGIONS' then
control.first_tab_regions('WHEN-TAB-PAGE-CHANGED');
elsif the_canvas = 'SECOND_TAB_REGIONS' then
control.second_tab_regions('WHEN-TAB-PAGE-CHANGED');
end if;
end;
WHEN-TAB-PAGE-CHANGEDコードは、ユーザーがタブを選択した結果コールされることになっています。タブ関連のシステム変数は、このモードでのみ有効です。このコードをプログラムにより起動する場合、他のイベントを渡してロジックを調整すると、タブ関連のシステム変数が参照されなくなります。
タブ・ハンドラのWHEN-NEW-ITEM-INSTANCEブランチは、ブロックの全フィールドにおけるユーザーの「タブ移動」、またはOracle Fromsがカーソルを自動的に移動した際(たとえば、必須フィールドがNULLの場合)の動作を処理します。
カーソルはスタック・キャンバスのあるタブ・リージョンのフィールドへ移動するので、スタック・キャンバスは自動的に呼び出されますが、対応するタブ・ページは呼び出されません。タブ・ハンドラのWHEN-NEW-ITEM-INSTANCEブランチにあるロジックは、現行スタック・キャンバスおよび現行項目と同期して「一番手前」のタブ・ページを保持します。
基本的なケースには、WHEN-NEW-ITEM-INSTANCEブランチは必要ありません(項目はスタック・キャンバスではなくタブ・ページに直接配置されています)。フィールドがタブ・ページに直接置かれているため、タブと現行フィールドをプログラムにより同期する必要はありません。スタック・キャンバスがある場合は常に、WHEN-NEW-ITEM-INSTANCEブランチが必要です(標準および高度なケース)。固定フィールド・キャンバスを処理するための特別なコードは必要ありません。
次に示すのは、FNDTABFF.txtファイル内にあるタブ・ハンドラのWHEN-NEW-ITEM-INSTANCEブランチです。
ELSIF (event = 'WHEN-NEW-ITEM-INSTANCE') THEN
if ((curr_canvas_name in ('MY_FIRST_ALT_REG_CANVAS',
'MY_SECOND_ALT_REG_CANVAS',
'MY_THIRD_ALT_REG_CANVAS')) and
(curr_canvas_name != current_tab)) then
set_canvas_property('TAB_ENTITY_REGIONS',
topmost_tab_page,
curr_canvas_name);
end if;
このコードは、対応するタブ・ページと完全に同じ名前を持つ代替リージョン・スタック・キャンバスに依存しています。次のコードを使用して、一番手前のタブを変更します。
set_canvas_property(...TOPMOST_TAB_PAGE...)
デフォルトの一番手前のタブ・ページは、Layout Editorの一番左に表示されるタブです。
Oracle Applicationsで使用される「動的タブ」には、2つの主なケースがあります。
フォーム起動時におけるタブの表示または非表示
フォーム・セッションにおけるタブの有効化または無効化(ただし表示したまま)
Set_Tab_Page_Property(...VISIBLE...)を使用して、フォーム起動時にタブを動的に非表示にできます。
Set_Tab_Page_Property(...ENABLED...)を使用して、フォーム・セッション中にタブを動的に有効化または無効化できます。通常、一定の条件下でタブを有効または無効にするフォームの別の場所に、コードを追加します。
Get_Tab_Page_Propertyを使用して、タブが有効であるか無効であるかのいずれかであるかをテストします。
DECLARE
my_tab_page_id TAB_PAGE;
my_tab_enabled VARCHAR2(32);
BEGIN
my_tab_page_id := FIND_TAB_PAGE('my_tab_page_1');
my_tab_enabled := GET_TAB_PAGE_PROPERTY (my_tab_page_id,
ENABLED)
IF my_tab_enabled= 'TRUE' THEN ...
現在一番手前ページになっているタブ・ページを、非表示または無効にはできないことに注意してください。
その値によってタブの有効化および無効化が制御される「マスター」フィールドの場合、特別なロジックが必要です。無効化するタブをユーザーがクリックした際の動作を、ロジックにより実現する必要があります。この場合、ユーザー・インタフェースはタブが実際に無効化されたかのように動作します。
この状況は、次のような場合に起こります。フィールドの値に基づいてタブが有効または無効になるフィールドがあるとします(タブ・ページ上でも、それ以外でも可)。マスター・フィールドがポップリスト、チェック・ボックス、またはオプション・グループである場合、有効化/無効化のロジックをWHEN-LIST-CHANGEDトリガーまたは同じ目的で使用されるトリガーに含めます。
別の対処方法が必要なケースもあります。マスター・フィールドがテキスト項目である場合です。この場合、ユーザーはマスター・フィールドの値を変更してタブの無効化などを行いますが、フィールドのWHEN-VALIDATE-ITEMロジックが起動する前にその(まだ有効な)タブをクリックします(これは、ユーザーがフィールドからタブ移動してWHEN-VALIDATE-ITEMロジックを起動する通常の方法ではなく、タブをクリックするということを意味します)。
ユーザーがタブをクリックする時点ではWHEN-VALIDATE-ITEMロジックが起動していないので、タブはまだ有効です。しかし、エンド・ユーザーから見るとタブは無効になったかのように動作し、無効になったタブはユーザーがクリックできないように動作する必要があります(タブは一番手前にはなりません)。クリックするとタブはただちにアクティブになるので、無効にするタブの場合はただちに一番手前のタブになります。その時点でプログラムにより無効化され、タブ・リージョンは前のマスター・フィールドの妥当性チェック時の状態へ戻る必要があります。ただし、タブが一番手前にあり、アクティブになっている間は無効にできません。
タブ・ハンドラのWHEN-TAB-PAGE-CHANGED部分にある妥当性チェック(item_scope)ロジックにより、フィールドのWHEN-VALIDATE-ITEMロジックが起動されます。WHEN-VALIDATE-ITEMロジックは、タブ・ページが前のページ(ユーザーがクリックする前)へ戻るのに必要な:system.tab_previous_page変数にアクセスできません。したがって、タブ・ハンドラには、タブ・ページの変更が成功した時点でパッケージ変数またはフォーム・パラメータに一番手前のタブ・ページの情報を保存するコードが必要です。この保存された値は、タブ・ページの変更が失敗した場合に、一番手前のタブ・ページを復元するために使用されます(エラーは、WHEN-VALIDATE-ITEMロジックの動作により発生します)。クリックしたタブが無効である場合は、タブ・ハンドラが(妥当性チェックのコール後に)動作しないように修正する必要があります。
場合によっては、次のトリガーに関するタブ関連コードを追加する必要があります。
KEY-CLRFRM
WHEN-NEW-FORM-INSTANCEまたはPRE-FORM
フォームの動作内容によっては、タブ・ページをKEY-CLRFRMの後の初期状態にリセットする必要があります。ハンドラにKEY-CLRFRMに関するブランチを追加して、次のようなコードを含めます。
set_canvas_property('TAB_ENTITY_REGIONS', topmost_tab_page,
'MY_FIRST_ALT_REG_CANVAS');
-- reset the tabs after KEY-CLRFRM
show_view('MY_FIRST_ALT_REG_CANVAS');
-- display the first stacked canvas
同様に、WHEN-NEW-FORM-INSTANCEまたはPRE-FORMに関するブランチを追加して、show_viewを実行することなどによりタブ・リージョンを初期化できます。
Oracle Formsでは、キャンバスの順序付けは保証されていません。場合によっては、フォームの起動時またはフォームの他の状況において、特別なshow_view()コマンドを含めて適切なキャンバスの順序付けを行う必要があります。
Oracle FormsのSet_tab_page_propertyおよびGet_tab_page_property(canvas.tabpage...)ビルトイン・ルーチンでは、次のプロパティが使用されます。
ENABLED
LABEL
VISIBLE
Get_Tab_Page_Propertyルーチンを使用して、タブが有効または無効のどちらであるかをテストします。
DECLARE
my_tab_page_id TAB_PAGE;
my_tab_enabled VARCHAR2(32);
BEGIN
my_tab_page_id := FIND_TAB_PAGE('my_tab_page_1');
my_tab_enabled := GET_TAB_PAGE_PROPERTY (my_tab_page_id, ENABLED)
IF my_tab_enabled= 'TRUE' THEN ...
この例では、TAB_ENTITY_REGIONSタブ・キャンバスの一番手前のタブ・ページ(つまり表示されているタブ・ページ)に、MY_SECOND_TAB_PAGEタブ・ページを設定しています。
set_canvas_property('TAB_ENTITY_REGIONS', topmost_tab_page,
'MY_SECOND_TAB_PAGE');
さらに、現行タブ・ページの名前を取得することもできます。
current_tab VARCHAR2(30) := get_canvas_property('TAB_ENTITY_REGIONS',
topmost_tab_page);
Oracle Applicationsリリース12では、代替リージョンにかわってタブ・リージョンを使用します。新しいコードには必ずタブ・リージョンを実装してください。
同時にレンダリングできない複数のリージョンがあるブロックでは、スタックされたキャンバスを使用して各リージョンを同時に、かつ1つのリージョン境界内で表示します。これらのスタックされたリージョンを「代替リージョン」と呼びます。
詳細は、『Oracle Applicationsフォーム・ベース製品のユーザー・インタフェース標準』を参照してください。
各代替リージョンには、ブロックで利用できるすべてのリージョンを含んでいる、ポップリスト制御要素があります。
代替リージョン・ポップリストの動作は、次の基準を満たしている必要があります。
代替リージョン・ポップリストは、「問合せ許可」属性を「Yes」に設定して、ブロックが問合せ入力モードの際に使用できるようにする必要があります。
KEY-MENUは、LOVを起動してユーザーが制御ポップリストで選択したのと同じリストを選択できるようにします。LOVのタイトルは「リージョン」です。制御ポップリストには、この機能なしではマウス以外からアクセスできないため、キーボード互換性のために必要な機能です。
ブロックLINESのコンテンツ・キャンバスORDERには、いくつかのフィールドがあります。最後のフィールドはITEMです。
LINESのキャンバスLINES_PRICEおよびLINES_ITEMには、代替リージョンがあります。リージョンには、LINES.ITEMがNULLではない場合にのみアクセスできます。LINES_PRICEの最初の項目は、LIST_PRICEです。LINES_ITEMの最初の項目は、DESCRIPTIONです。
制御ブロックでポップリストを作成し、現在のリージョンを選択します。ポップリストは問合せ可能で、ナビゲートはできません。ポップリストには、各リージョンの分かりやすい名前と対応する値(リージョンのキャンバス名と同じ)が表示されます。
ブロックCONTROLには、LINES_REGIONSという名前(ブロック名に_REGIONSを付けたもの)の問合せ可能で、ナビゲート不可能なポップリストがあり、次の値と、値に続く内部値が含まれます: 「価格情報」(LINES_PRICE)、「品目情報」(LINES_ITEM)。
CONTROLブロックを次のように参照します。
フォームの起動時に、制御ポップリストを含むブロックを参照して、インスタンス化を行う必要があります。
CONTROLブロックの最初の項目として、DUMMYという名前のテキスト項目を作成します。テキスト項目の設定を、「可視」、「使用可能」、「キーボードで移動可能」、「位置」を0,0、WD=0、HT=0、および+-Length=1にします。さらに、表示される最初のキャンバスに配置します。
WHEN-NEW-FORM-INSTANCEで、2つのGO_BLOCK()コールを、1つはCONTROLブロックに、もう1つは「最初のナビゲーション・データ・ブロック」に対して作成します。
KEY-CLRFRMを処理するコード内で、同様のGO_BLOCKコールを行うことを確認します。
最初に表示するリージョンを次のとおり設定します。
Oracle Forms Designer内で、代替リージョン・セットの最初にスタックされたキャンバスを表示するよう指定し、セットの他のキャンバスはすべて表示しないよう設定して起動時のパフォーマンスを改善します。
Oracle FormsのObject Navigatorのリスト内でキャンバスを整理することにより、スタックされたキャンバスを注意深く順序付けます(リストに最初にスタックされたキャンバスが、最初に表示されます)。さらに、ユーザーが代替リージョンのフィールド間をタブ移動する際も、項目を適切な順序で並べる必要があります。
ヒント: スタックされたキャンバスを参照する際に、順序が乱れることがあります。そのような場合、フォームの起動時や、ウィンドウを最初に表示するときに、SHOW_VIEWを発行して適切なキャンバスのレンダリングを強制します。
スタック・キャンバスがすべてちょうど同じサイズになっていることと、コンテンツ・キャンバスでちょうど同じスペースを占めていることを確認してください。
次の例にあるように、項目ハンドラ・プロシージャを作成して、どのリージョンを表示するかを制御します。フォームの例では、フィールドLINES.ITEMがNULLでない場合はリージョンへのアクセスを許可していないことに注意してください。
PACKAGE BODY control IS
g_canvas_name VARCHAR2(30) := null;
PROCEDURE lines_regions(event varchar2) IS
target_canvas_name VARCHAR2(30);
curr_canvas_name VARCHAR2(30) :=
get_item_property(:system.cursor_item,
ITEM_CANVAS);
BEGIN
IF (event = 'WHEN-NEW-ITEM-INSTANCE') THEN
-- Check if the poplist and the canvas are out of synch
-- to prevent flashing if they are not.
IF ((curr_canvas_name in ('LINES_PRICE', 'LINES_ITEM')) AND
(curr_canvas_name != :control.lines_regions)) THEN
:control.lines_regions := curr_canvas_name;
g_canvas_name := curr_canvas_name;
END IF;
ELSIF (event = 'WHEN-LIST-CHANGED') THEN
target_canvas_name := :control.lines_regions;
-- The following is optional code to disallow access
-- to certain regions under certain conditions
-- Check that the region is accessible. Always allow access
-- during queries.
IF (:SYSTEM.MODE = 'ENTER-QUERY') THEN
null;
ELSE
IF (:lines.item is null) THEN
FND_MESSAGE.SET_NAME('OE', 'OE_ENTER_ITEM_FIRST');
FND_MESSAGE.ERROR;
:control.lines_regions := g_canvas_name;
RAISE FORM_TRIGGER_FAILURE;
END IF;
-- End of optional code
END IF;
-- Display the region. If in the same block, go to the
-- first item in the region.
IF curr_canvas_name in ('LINES_PRICE', 'LINES_ITEM') THEN
hide_view(curr_canvas_name);
END IF;
show_view(target_canvas_name);
IF (:system.cursor_block = 'LINES') THEN
IF (target_canvas_name = 'LINES_PRICE') THEN
-- Go to the first item in the canvas LINES_PRICE
go_item('lines.list_price');
ELSIF (target_canvas_name = 'LINES_ITEM') THEN
-- Go to the first item in the canvas LINES_ITEM
go_item('lines.description');
END IF;
END IF;
g_canvas_name := target_canvas_name;
ELSE
fnd_message.debug('Invalid event passed to
control.lines_regions');
END IF;
END lines_regions;
END control;
ユーザーがKEY-MENUによりLOVを表示してリストから値を選択した後、WHEN-LIST-CHANGEDハンドラはリージョンを切り替えます。
次のトリガーをコールします。
トリガー: LINESブロックのブロック・レベルWHEN-NEW-ITEM-INSTANCE
CONTROL.LINES_REGIONS('WHEN-NEW-ITEM-INSTANCE');
トリガー: LINESブロックのブロック・レベルKEY-MENU(実行階層は「オーバーライド」)
IF APP_REGION.ALT_REGIONS('CONTROL.LINES_REGIONS') THEN
CONTROL.LINES_REGIONS('WHEN-LIST-CHANGED');
END IF;
トリガー: CONTROL.LINES_REGIONSの項目レベルWHEN-LIST-CHANGED
CONTROL.LINES_REGIONS('WHEN-LIST-CHANGED');
これらのトリガーは、問合せ入力モードで起動します。
この項の内容は次のとおりです。
デフォルトでは、複製レコードはフォーム・レベルで使用不可になっています。これは、次の理由によります。
特殊列ROW_IDが複製されており、存在する場合は手動で解除する必要がある
項目にもう有効でない時間依存データが含まれる場合でも、レコードは有効であるとマークされる
デフォルトがオーバーライドされる
ブロックの多くで、複製レコードに意味が与えられていない(モーダル・ダイアログ、検索ブロックなど)
どのブロックにおいても、複製レコードを有効にする場合はコードを作成する必要があります。一意キーの処理、必要な場合はデフォルトの再適用、および複製されたデータがまだ有効かどうかの確認を行う必要があります。どれもデフォルトでは実行されず、エラーまたはデータの破損が発生する可能性があります。
一般に、値が必ず一意である場合でも、すべてのレコードを複製します。ユーザーは、前の値とほとんど同じ一意の値を作成する場合があります。
次の場合には、デフォルトをオーバーライドしないでください。
ユーザーが項目を変更できない
新規レコードに、特定の値が必ず含まれている
項目が連番になっており、ほとんどの場合デフォルトが正確な値である
ブロックorderに、項目order_numberとorder_dateがあり、それぞれが順序order_SおよびSYSDATEによりデフォルト設定されており、ユーザーによる変更はできないとします。項目statusでは、新しい順序に「オープン」を含める必要がありますが、ユーザーはいつでもステータスを「記帳」に変更して順序を登録できます。
イベント・ハンドラ・プロシージャを次のように作成します。
PACKAGE BODY order IS
PROCEDURE KEY_DUPREC IS
CURSOR new_order_number IS SELECT order_S.nextval
FROM sys.dual;
BEGIN
DUPLICATE_RECORD;
open new_order_number;
fetch new_order_number into :order.order_number;
close new_order_number;
:order.status : = 'Open';
:order.order_date := FND_STANDARD.SYSTEM_DATE;
:order.row_id := null;
END KEY_DUPREC;
END order;
次のトリガーを使用して、イベント・ハンドラ・プロシージャをコールします。
トリガー: orderのKEY-DUPREC
order.KEY_DUPREC;
ブロックのすべてのレコードについて、項目を順番に再ナンバリングするには、ユーザー定義のトリガーを作成して、順序変数の増分と順序項目の設定を行います。プロシージャAPP_RECORD.FOR_ALL_ RECORDSを使用して、各レコードに1回ずつトリガーを実行します。
レコードの作成時に採番するには、順序番号を含む変数または項目を作成します。WHEN-CREATE-RECORDトリガーを作成して、変数の場合は順序番号の増分を、項目の場合は順序番号を指定します。ただし、ウィンドウのすべてのレコードを再ナンバリングする場合、プロシージャAPP_RECORD.FOR_ALL_RECORDSを使用します。
問合せまたはコミット後に項目を再ナンバリングする場合、レコードの状態をリセットするとレコードの変更はマークされません。
ブロックlinesには、項目line_numberがあります。レコードが削除された場合、line_numberを再ナンバリングする必要があります。
項目ハンドラ・プロシージャを次のように作成します。
PACKAGE BODY lines IS
line_number_seq number := 0;
PROCEDURE delete_row IS
BEGIN
line_number_seq := 0;
APP_RECORD.FOR_ALL_RECORDS('reseq_line_number');
END delete_row;
END lines;
次のように、ユーザー定義のトリガーRESEQ_LINE_NUMBERを作成します。
lines.line_number_seq := lines.line_number_seq + 1;
:lines.line_number := lines.line_number_seq;
次のトリガーを使用して、項目ハンドラ・プロシージャをコールします。
トリガー: KEY-DELETE
lines.line_number('KEY-DELETE');
警告: このようなタイプの処理によって生じる結果に注意を払ってください。特に、次の点を考慮してください。
レコードの問合せがブロック内で大量に行われる場合、1つずつループしていくと非常に時間がかかる場合があります。
ユーザーに問合せ入力を許可している場合、ブロック内のすべてのレコードが現在の問合せに使用できるわけではありません。
一意キーの一部である値を変更する場合、コミット時にエラーが発生することがあります。これは、現在コミットされているレコードがすでにデータベースに登録されている他のものと競合することがあるためで、レコードをブロック内で変更したことがある場合も同様です。
2つのフォームがすでに開いており、一方のフォームからもう一方へナビゲートする際に情報を渡すには、WHEN-FORM-NAVIGATEトリガーを使用します。このトリガーを直接コーディングするのではなく、グローバル変数によって情報を渡すようにしてください。
このトリガーを使用するには、GLOBAL.WHEN_FORM_NAVIGATEというグローバル変数をユーザー定義トリガーの名前とともに設定します。フォームにナビゲートすると、このトリガーが起動します。
WHEN-FORM-NAVIGATEトリガーは、GO_FORMビルトインを使用して、プログラムによってフォームにナビゲートするときに起動します。したがって、このトリガーは、すべてのフォームから参照されます。
フォームにナビゲートして、特定の項目を問い合せることは一般的です。たとえば、受注入力フォームORDERSとカタログ・フォームCATALOGSがあり、ORDERSフォームからCATALOGSフォームへナビゲートして特定の部品番号を問い合せるとします。
ORDERSフォームで、GLOBAL.PART_NUMBERというグローバル変数を作成し、問合せを行う値を指定します。
ORDERSフォームで、GLOBAL.WHEN_FORM_NAVIGATEというグローバル変数を作成し、この変数の値に文字列「QUERY_PART_NUMBER」を指定します。
CATALOGSフォームで、ユーザー定義トリガー「QUERY_PART_NUMBER」を作成します。このトリガーに、EXECUTE_QUERYをコールして問合せモードを入力します。
CATALOGSフォームで、copy('GLOBAL.PART_NUMBER, 'PARTS_BLOCK.PART_ NUMBER')をコールするPRE-QUERYトリガーを作成します。作成後に、copy('','GLOBAL.PART_NUMBER')をコールします。GLOBAL.PART_NUMBERに値がある場合は問合せ基準の一部になります。