ヘッダーをスキップ

Oracle Applications開発者ガイド
リリース12
E06048-01
目次へ
目次
前のページへ
前へ
次のページへ
次へ

ウィンドウ、ブロックおよびリージョンの動作の制御

ウィンドウの動作の制御

ウィンドウの動作の制御には、ウィンドウが開くときの位置を指定するコーディング・ロジック、どのような条件でどのウィンドウが閉じるかの制御、詳細ウィンドウへのコンテキスト依存のタイトル付与などが含まれます。個々のウィンドウのブロック間にマスター詳細関連が存在する場合は、その状況に応じたロジックもコーディングする必要があります。

関連項目: マスター詳細関連のコーディング

ウィンドウが開くときの位置設定

「発注」ヘッダー・ウィンドウに、「明細」というラベルのボタンがあり、他のウィンドウのLINESブロックへ移動できるようにする場合を考えます。

  1. 次のトリガーを追加または変更します。

  2. APP_CUSTOM.OPEN_WINDOWを次のように修正します。

     IF wnd = 'LINES' THEN
    
       APP_WINDOW.SET_WINDOW_POSITION('LINES',
    
                           'CASCADE','HEADER');
    
       go_block('LINES');
    
    END IF;
    
    

    使用可能なスタイルは次のとおりです。

ウィンドウを閉じる

非モーダル・ウィンドウ(モーダル・ウィンドウ以外)を閉じるイベントは、すべてAPP_CUSTOM.CLOSE_WINDOWへ渡されます。TEMPLATEフォームで提供されるデフォルト・コードは次のとおりです。

他の動作に対応するためには、このプロシージャを修正する必要があります。具体的には、ブロック調整機能と詳細ウィンドウを処理するように修正します。

ウィンドウを閉じる前に、カーソルを外に移動させる必要があることに注意してください。そうしない場合、再びウィンドウが自動的に開くことになります。

フォームの最初のウィンドウを閉じるには(「ファイル」->「フォームのクローズ」と同等)、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ウィンドウのタイトル・ルーチンにより追加されます。ベース・ウィンドウ・タイトルに、これらの文字が含まれることはありません。ハイフン(-)を使用する場合、スペースでハイフンを囲まないでください。つまり、ハイフンの前後にスペースを入れることはできません。

動的タイトルの例

「仕訳データの入力」フォームで、「仕訳明細」ウィンドウに現在の「会計帳簿」および「仕訳」名を表示する場合を考えます。

  1. Oracle Forms Developerで、「明細」ウィンドウのタイトルを、「仕訳明細」に設定します。

  2. 「仕訳」ブロックのPRE-RECORDトリガーを次のようにコーディングします。

    app_window.set_title('LINES', name_in('Journal.SOB'),
    
     :journal.name);
    
    
  3. journal.namesフィールドのWHEN-VALIDATE-ITEMトリガーを次のようにコーディングします。

    app_window.set_title('LINES', name_in('Journal.SOB'),
    
     :journal.name);
  4. ウィンドウのベース・タイトルを変更する必要がある場合には、SET_WINDOW_ PROPERTY(...TITLE...)をコールします。それ以降APP_WINDOW.SET_ TITLEがコールされる際は常に、新しいベース・タイトルが保持されます。

ブロックの動作の制御

ブロックの動作の制御は、マスター詳細関連のコーディングと組合せブロックの実装を含みます。

関連項目: マスター詳細関連のコーディングおよび組合せブロックの実装

マスター詳細関連のコーディング

詳細ブロックがそのマスターとは別のウィンドウにあり、各ウィンドウが非モーダルである場合、詳細ブロックにはユーザーが即時調整と遅延調整を切り替えることのできる手段が必要です。これにより、ユーザーはブロックを表示したまま、マスター・レコードが変更されたときに詳細レコード調整のパフォーマンス・コストを制御できるようになります。

詳細ブロックが非表示の場合、その調整は常に遅延である必要があります。プロシージャAPP_WINDOW.SET_COORDINATIONを使用して、異なるウィンドウのマスター詳細ブロックを調整します。

関連項目: APP_WINDOW: ウィンドウ・ユーティリティ

サンプル・コードでは次のオブジェクトを使用します。

ウィンドウ間の調整

  1. 詳細ブロックへナビゲートするボタンを作成します。

  2. 詳細ウィンドウの制御ブロックで「調整」チェック・ボックスを作成し、ウィンドウが開くときの即時調整または遅延調整のユーザー作業環境を設定します。チェック・ボックスにはCHECKBOX_COORDINATIONプロパティ・クラスが必要であり、選択した場合は「IMMEDIATE」の値に、選択を解除した場合は「DEFERRED」の値になります。チェック・ボックス値のデフォルトは、選択した状態(IMMEDIATE)です。

  3. 項目ハンドラ・プロシージャを次のように作成します。

    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;
    
    
  4. 次のように、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;
    
    
  5. 次の方法で、フィールドおよびイベント・ハンドラ・プロシージャをコールします。

    トリガー: 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度出てくるため、そのような項目の値の調整を管理する必要があります。「項目と同期」プロパティによって、これを自動的に行います。「スイッチャ」と呼ばれるフィールドを使用して、様々な状況でブロックのどの部分にナビゲートするかを制御します。「スイッチャ」フィールドは、ブロックの中で最初にナビゲート可能な項目です。カーソルが「スイッチャ」に入ると、ブロックの各「詳細」または「要約」部分の最初の項目へただちに移動します。

  1. 組合せブロックの設定

    2つのウィンドウおよびキャンバスを作成して、異なるブロック部分を保持します。「要約」部分には、ブロックの非ミラー項目を使用します。項目を複製し、「詳細」部分を作成します。組合せブロックの「詳細」部分は、順番の最初に配置します。したがって、ユーザーが必要な項目に記入せずにコミットする場合、Oracle Formsがカーソルを「詳細」ブロックのその項目に移動します。

  2. 項目プロパティの設定

    ミラー項目に対して、項目名を変更してミラー元の実際の項目に反映します(たとえば、「status」のミラー項目名を「status_mir」にします)。「項目と同期」プロパティを設定し、「データベース項目」プロパティが「Yes」に設定されていることを確認してください(同期化項目が、実表の項目である場合)。

    「要約」にあるブロック・レベルの「表示項目数」プロパティを設定します。これは、「表示項目数」プロパティを明示的に設定していなければ、項目により使用されます。「詳細」部分の項目は同じ値を取得しないので、「表示項目数」プロパティを明示的に1に設定します。

    ユーザーが「詳細」から「要約」へタブを移動するのを避けるため、最初の「詳細」項目に「前ナビゲーション項目」プロパティを、最後の「詳細」項目に「次ナビゲーション項目」プロパティを設定します。

    「レコードの変更」の標準マルチ・レコード・ブロックのナビゲーション動作を規定するため、「要約」部分にある最初のナビゲート可能項目のKEY-PREV-ITEMトリガー(問合せ入力モードではない場合に起動)でAPP_COMBO.KEY_PREV_ITEMをコールし、「要約」部分にある最後のナビゲート可能項目のKEY-NEXT-ITEMトリガー(問合せ入力モードではない場合に起動)でnext_recordをコールします。

    既存のブロックを組合せブロックに変換する場合、すべての既存のトリガーにおける参照が、すべてのフィールドに2つのインスタンスが存在することを認識するように忘れずに変更してください。

    関連項目: APP_COMBO: 組合せブロックAPI

  3. ドリルダウン・レコード・インディケータ

    execute_trigger('SUMMARY_DETAIL')を実行するドリルダウン・レコード・インディケータを追加します。

  4. レコード・カウント・パラメータ

    パラメータを作成して、現在のブロックの部分のレコード・カウンタを保存します。パラメータ名は<block>_RECORD_COUNTとします。ここで、<block>は、組合せブロックの名前です。APPCOREコードは、このネーミング標準により決まります。この情報を利用して、ブロックのどの部分をナビゲートするかを決定します。最初にカーソルを「要約」に配置するには、パラメータにはNUMBERというデータ型が必要で、デフォルト値を2にします。(最初のカーソルの位置を「詳細」部分にする場合、デフォルト値を1に設定します。)

    次のコードを含む、ブロック・レベルのWHEN-NEW-ITEM-INSTANCEトリガー(実行階層は「前」)を作成します。

     :PARAMETER.<block>_RECORD_COUNT :=
    
    GET_ITEM_PROPERTY(:SYSTEM.CURSOR_ITEM,
    
                             RECORDS_DISPLAYED);
    
    
  5. スイッチャ

    テキスト項目を作成し、プロパティ・クラス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;
    
    
  6. 「要約/詳細」メニュー項目

    次のコードを含む、ブロック・レベルの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をフォーム・レベルで有効にし、組合せブロックではないブロックについてはブロック・レベルで無効にします。

  7. 初期ナビゲーションおよびウィンドウ操作

    組合せブロックが、フォームの最初のブロックである場合、次のコールにより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段階のコーディング難度

3段階の難易度があり、それぞれ異なるレイアウト方法およびコーディング方法が要求されます。

レイアウト方法の違いには、スタック・キャンバスを使用するかどうか、およびいくつ使用するかといったことが含まれます。そして、コーディング方法の違いには、スタック・キャンバスを使用したタブの動作の処理に必要な追加のコードが含まれます。

基本的なケース: スクロールなし、固定フィールドなし

基本的なケースには、異なるページでフィールドが繰り返されることのない単一行タブ・ページが含まれます。通常、これらはフォームの独立したブロックになっています。

タブ・ページにつき1つのブロックがあり、それぞれに独立したブロック・スクロールバーがあるが、フィールドの水平スクロールはできないタブ・リージョンのように、複数の独立した複数行ブロックを伴うフォームがある場合、同様に基本的なケースとしてコーディングできます。たとえば、システム管理者職責における「ユーザー」ウィンドウは、基本的なケースに該当します。

基本的なケースでは、項目を直接タブ・ページに配置します。基本的なケースにスタック・キャンバスは必要ありません。

標準的なケース:スクロールあり、固定フィールドなし

標準的なケースには、異なるページでフィールドが繰り返されることのない単一行タブ・ページが含まれますが、タブ・ページ内の全ページにアクセスできるスクロールバーが必要です。通常、これらのタブ・ページは、フォームの独立したブロックになっています。

タブ・ページにつき1つのブロックで、それぞれに独立したブロック・スクロールバーがあり、フィールドの水平スクロールが可能なタブ・リージョンのように、複数の独立した複数行ブロックを伴うフォームがある場合、同様に標準的なケースとしてコーディングできます。ブロック・スクロールバーおよびボタンのような「固定」(ただし共有されない)オブジェクトは、このケースのタブ・ページに直接配置できます。

標準的なケースでは、項目をタブ・ページの手前のスタック・キャンバスに配置して、フィールドのスクロールを容易にできます。

高度なケース: 固定フィールドあり、スクロールは任意

高度なケースでは、様々なタブ・ページ間で共有される固定フィールドを処理できます。このケースには、複数のタブ・ページにまたがる複数行ブロックが含まれます。通常、固定フィールドにはコンテキスト・フィールド、現行またはドリルダウンのレコード・インディケータ、記述フレックスフィールド、およびブロック・スクロールバーが含まれます。

フレックスフィールドの場合は、項目をタブ・ページの手前のスタック・キャンバスに配置して、フィールドのスクロールを容易にできます。フレックスフィールドには特別なスタック・キャンバスが必要で、タブ・ハンドラにコードを追加する必要があります。

タブ・リージョンの実装

タブ・リージョンの実装は、基本的に主要な2つの段階からなっています。

次の手順で、Oracle Applicationsの標準に基づいたタブ・リージョンの実装方法を説明します。これらの手順は、各手順で説明されているような違いはありますが、3つのケース(基本、標準、高度)のすべてに適用されます。

関連項目: Forms Developerでのレイアウトの作成

タブ・ハンドラのコーディング

Forms Developerでのレイアウトの作成

Forms Developerでレイアウトを作成する手順を次に示します。

  1. タブ・キャンバスを作成します。タブ・キャンバスに、標準形式TAB_ENTITY_REGIONS(ENTITYはLINESなどのエンティティ)または同様の名前を付けます。たとえば、タブ・キャンバスの名前はTAB_LINES_REGIONSのようにできます。TAB_CANVASプロパティ・クラスを適用します。

    タブ・キャンバスのウィンドウ・プロパティを設定すると、タブ・キャンバスが適切なウィンドウに表示されます。タブ・キャンバスのウィンドウ・プロパティを適切なウィンドウに設定しない場合、Form Builderで「ビュー」->「スタック・ビュー」メニューを選択してコンテンツ・キャンバスにタブ・キャンバスは表示できません。

  2. タブ・キャンバスを調整します。キャンバスの順序をコンテンツ・キャンバスの後、および手前に表示されるすべてのスタック・キャンバスより前に置きます。Layout Editorでそのビューポートを調整します。同時にコンテンツ・キャンバスを表示すると、タブ・キャンバスの位置をうまく調整できます。

  3. タブ・ページを作成します。

    標準および高度なケースの場合、タブ・ページの名前は対応する「代替リージョン」スタック・キャンバスの名前と一致している必要があります。

  4. タブ・ページを調整します。各タブ・ページにプロパティ・クラスTAB_PAGEを適用し、タブ・ページ・ラベルを設定します。Object Navigatorのタブ・ページの順序を、項目タブの順序に一致するように指定します。

  5. 高度なケースの場合のみ、固定フィールド・スタック・キャンバスを作成し、その名前を(tab_canvas)_FIXEDとします。順序を、タブ・キャンバスの後、かつ高度なケースで作成するすべての「代替リージョン」スタック・キャンバスの前に置きます。プロパティ・クラスCANVAS_STACKED_FIXED_FIELDを適用します。フレックスフィールド・キャンバス・ビューポートを、ちょうどタブ・キャンバス・ビューレポートの内側に収まるように設定します。

  6. 標準および高度なケースの場合のみ、「代替リージョン」スタック・キャンバスを作成します。これらのキャンバスは、ビューポートのサイズと位置をすべて同じにする必要があります。代替リージョン・スタック・キャンバスの「可視」プロパティを確認します(最初のキャンバスのみを表示する場合「Yes」に設定します)。

    高度なケースの場合、これらの「代替リージョン」キャンバスにより固定フィールド・キャンバスの一部(すべてではありません)が隠れてしまいます。ビューポートの位置とサイズが、固定フィールド・キャンバスに対して適切な位置に設定されているかどうかを確認してください。

  7. 項目を適切なタブ・ページまたはスタック・キャンバスに配置します。ブロック・スクロールバーがある場合、キャンバスの右端に配置します。

    スタック・キャンバスを使用している場合、スタック・キャンバスはタブ・ページに直接配置されているフィールドをオーバーラップしない点に注意してください。同様に、どの「代替リージョン」スタック・キャンバスも、固定フィールド・スタック・キャンバスの項目をオーバーラップすることはありません。

  8. レイアウトを調整します。フィールド・プロンプトを、フィールドのプロパティのように適宜設定します。

    タブ・リージョンのレイアウトを設定する際の注意: タブ・リージョンのフィールドおよび他の要素のレイアウトを設定する際の根本的な基準は、見た目が美しいという点です。これには、タブ・ページの内側および外側に十分なスペースを残して、過度に雑然としたレイアウトにしないということが含まれます。この点を満たすために必要なレイアウト設定は、1通りではありません。たとえば、タブ・リージョンの最後にある複数行チェック・ボックスの場合、テキスト項目を同じ場所に配置する場合よりも、タブ・ページの端との間に多くの空白が必要な場合があります。

    Forms DeveloperのLayout Editorでは、タブおよびスタック・キャンバスにOracleルック・アンド・フィールを利用できない点にも注意してください。Oracleルック・アンド・フィールは、実行時のみ利用できます。設計時には、見た目ではなくビューポートの数値を使用する必要があります。

    詳細は、『Oracle Applicationsフォーム・ベース製品のユーザー・インタフェース標準』を参照してください。

タブ・ハンドラのコーディング

タブ・リージョンの実装における2番目の段階であるタブ・ハンドラのコーディング手順を次に示します。

  1. タブ・ハンドラをコーディングします。次の2つのテンプレート・ファイルが用意されており、簡単にハンドラをコーディングできます。

    FNDTABS.txtおよびFNDTABFF.txtの場所は、FND_TOP/resource(ファイル名は小文字の場合があります)の下です。適切なタブ・ハンドラのテンプレート・ファイルを選択してください(FNDTABS.txtまたはFNDTABFF.txt)。フォーム(通常ブロック・パッケージまたは制御パッケージ内にあります)またはライブラリにハンドラ・テキストをインポートし、フォームに合うように変更します。フォーム・オブジェクト名にあわせ、特に必要な動作を実行するように変更します。ファイルには多くのコメントが含まれており、ファイルの変更を適切な部分に行うのに役立ちます。

  2. トリガーからタブ・ハンドラをコールします。フォーム・レベルの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-TAB-PAGE-CHANGEDロジックにより次の動作が実行されます。

WHEN-TAB-PAGE-CHANGEDトリガーは、ユーザーがタブをクリックした場合のみ起動します。プログラムにより起動させることはできず、フォーム・レベルでのみ使用できます。

FNDTABS.txt内の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ブランチのテキスト

次に示すのは、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トリガーの変数

次の変数は、WHEN-TAB-PAGE-CHANGEDトリガー(またはこのトリガーによりコールされるコード)内でのみ有効です。

WHEN-TAB-PAGE-CHANGEDロジックにおける妥当性チェック

妥当性チェックは、次の行を含むハンドラの一部です。

 validate(item_scope);

これに、妥当性チェックが失敗した場合にタブを元の値にリセットするコードが続きます。

チェック・ルーチンがコールされると、ユーザーがフィールドの外にタブ移動した場合と同様に、現行フィールドの妥当性チェックが強制されます。この妥当性チェックには、有効な値(データ型、値の範囲など)を含むフィールドのチェックと、項目に適用可能なすべてのWHEN-VALIDATE-ITEMロジックの起動が含まれます。妥当性チェックが必要なのは、ユーザーがタブをクリックするとただちにWHEN-TAB-PAGE-CHANGEDトリガーが起動するためです(ユーザーがタブをクリックする前にいたフィールドのWHEN-VALIDATE-ITEMトリガーは、WHEN-TAB-PAGE-CHANGEDトリガーより前に起動することはありません)。

フォームを問合せのみに使用する場合、妥当性チェックは必要なく、タブ・ハンドラから削除できます。

問合せ入力モードでのWHEN-TAB-PAGE-CHANGEDのバリエーション

タブ・リージョンに問合せ可能でないフィールドがある場合、状況によってはロジックを調整して問合せ入力モードでの操作を許可する必要があります。すべてのgo_itemコールが問合せ可能フィールドに移動しているはずなので、ユーザーが問合せ入力モードになっているかどうかをテストして適切なフィールドに移動する必要があります。

問合せ入力モードでのテストは次のように行います。

 IF :system.mode = 'ENTER-QUERY' THEN ...

フォーム・レベルのWHEN-TAB-PAGE-CHANGEDトリガー

フォームに、タブ・セットが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-TAB-PAGE-CHANGEDコードは、ユーザーがタブを選択した結果コールされることになっています。タブ関連のシステム変数は、このモードでのみ有効です。このコードをプログラムにより起動する場合、他のイベントを渡してロジックを調整すると、タブ関連のシステム変数が参照されなくなります。

WHEN-NEW-ITEM-INSTANCEロジック

タブ・ハンドラの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ブランチのテキスト

次に示すのは、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

フォームの動作内容によっては、タブ・ページを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

同様に、WHEN-NEW-FORM-INSTANCEまたはPRE-FORMに関するブランチを追加して、show_viewを実行することなどによりタブ・リージョンを初期化できます。

Oracle Formsでは、キャンバスの順序付けは保証されていません。場合によっては、フォームの起動時またはフォームの他の状況において、特別なshow_view()コマンドを含めて適切なキャンバスの順序付けを行う必要があります。

タブ・ページ・プロパティのテスト

Oracle FormsのSet_tab_page_propertyおよびGet_tab_page_property(canvas.tabpage...)ビルトイン・ルーチンでは、次のプロパティが使用されます。

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フォーム・ベース製品のユーザー・インタフェース標準』を参照してください。

各代替リージョンには、ブロックで利用できるすべてのリージョンを含んでいる、ポップリスト制御要素があります。

代替リージョン・ポップリストの動作

代替リージョン・ポップリストの動作は、次の基準を満たしている必要があります。

例: 代替リージョンのコーディング

ブロックLINESのコンテンツ・キャンバスORDERには、いくつかのフィールドがあります。最後のフィールドはITEMです。

LINESのキャンバスLINES_PRICEおよびLINES_ITEMには、代替リージョンがあります。リージョンには、LINES.ITEMがNULLではない場合にのみアクセスできます。LINES_PRICEの最初の項目は、LIST_PRICEです。LINES_ITEMの最初の項目は、DESCRIPTIONです。

  1. 制御ブロックでポップリストを作成し、現在のリージョンを選択します。ポップリストは問合せ可能で、ナビゲートはできません。ポップリストには、各リージョンの分かりやすい名前と対応する値(リージョンのキャンバス名と同じ)が表示されます。

    ブロックCONTROLには、LINES_REGIONSという名前(ブロック名に_REGIONSを付けたもの)の問合せ可能で、ナビゲート不可能なポップリストがあり、次の値と、値に続く内部値が含まれます: 「価格情報」(LINES_PRICE)、「品目情報」(LINES_ITEM)。

  2. CONTROLブロックを次のように参照します。

    フォームの起動時に、制御ポップリストを含むブロックを参照して、インスタンス化を行う必要があります。

  3. 最初に表示するリージョンを次のとおり設定します。

    Oracle Forms Designer内で、代替リージョン・セットの最初にスタックされたキャンバスを表示するよう指定し、セットの他のキャンバスはすべて表示しないよう設定して起動時のパフォーマンスを改善します。

    Oracle FormsのObject Navigatorのリスト内でキャンバスを整理することにより、スタックされたキャンバスを注意深く順序付けます(リストに最初にスタックされたキャンバスが、最初に表示されます)。さらに、ユーザーが代替リージョンのフィールド間をタブ移動する際も、項目を適切な順序で並べる必要があります。

    ヒント: スタックされたキャンバスを参照する際に、順序が乱れることがあります。そのような場合、フォームの起動時や、ウィンドウを最初に表示するときに、SHOW_VIEWを発行して適切なキャンバスのレンダリングを強制します。

    スタック・キャンバスがすべてちょうど同じサイズになっていることと、コンテンツ・キャンバスでちょうど同じスペースを占めていることを確認してください。

  4. 次の例にあるように、項目ハンドラ・プロシージャを作成して、どのリージョンを表示するかを制御します。フォームの例では、フィールド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ハンドラはリージョンを切り替えます。

  5. 次のトリガーをコールします。

    トリガー: 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');
    
    

    これらのトリガーは、問合せ入力モードで起動します。

ウィンドウでのレコードの制御

この項の内容は次のとおりです。

レコードの複製

複製レコードが、デフォルトで使用不可である理由

デフォルトでは、複製レコードはフォーム・レベルで使用不可になっています。これは、次の理由によります。

どのブロックにおいても、複製レコードを有効にする場合はコードを作成する必要があります。一意キーの処理、必要な場合はデフォルトの再適用、および複製されたデータがまだ有効かどうかの確認を行う必要があります。どれもデフォルトでは実行されず、エラーまたはデータの破損が発生する可能性があります。

一般に、値が必ず一意である場合でも、すべてのレコードを複製します。ユーザーは、前の値とほとんど同じ一意の値を作成する場合があります。

次の場合には、デフォルトをオーバーライドしないでください。

ブロックorderに、項目order_numberorder_dateがあり、それぞれが順序order_SおよびSYSDATEによりデフォルト設定されており、ユーザーによる変更はできないとします。項目statusでは、新しい順序に「オープン」を含める必要がありますが、ユーザーはいつでもステータスを「記帳」に変更して順序を登録できます。

  1. イベント・ハンドラ・プロシージャを次のように作成します。

    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;
    
    
  2. 次のトリガーを使用して、イベント・ハンドラ・プロシージャをコールします。

    トリガー: 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を再ナンバリングする必要があります。

  1. 項目ハンドラ・プロシージャを次のように作成します。

     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;
    
    
  2. 次のように、ユーザー定義のトリガーRESEQ_LINE_NUMBERを作成します。

    lines.line_number_seq := lines.line_number_seq + 1;
    
    :lines.line_number := lines.line_number_seq;
    
    
  3. 次のトリガーを使用して、項目ハンドラ・プロシージャをコールします。

    トリガー: 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フォームへナビゲートして特定の部品番号を問い合せるとします。