コントロールで発生するイベント

Control の各クラスはインタラクティブな動作に対応するように設計されていて、ユーザーがマウスやキーボードの操作によってトリガする 1 つ以上のイベントに応答します。 前述のとおり、コントロール メカニズムの UI 部分では一般的な (または「未加工」) イベントを受け取り、コントロールで適合可能なイベントを発生させます。 ダイナミック イベント ハンドラをコントロールにアタッチし、発生したコントロール適合イベントへの応答としてこれらを実行することができます。
たとえば、ユーザーがテキスト フィールドに入力したときにテキスト フィールドの value プロパティを変化させるだけでなく、テキスト フィールドで ValueChanged イベントを発生させます。 続いてユーザーが [Enter] キーを押すかテキスト フィールドの外側にカーソルを移動すると、そこで ValueFinished イベントを発生させます。 ValueChanged および ValueFinished は、コントロールのみに適合可能な 2 つのイベント タイプの例です。 具体的には、これらはValue コントロール (value に関連付けられているコントロール) に適合されるものです。
さまざまなコントロール適合イベントは、通常ユーザーのコントロール操作に応じてコントロールで発生します。 次のようなイベントが含まれます。
各コントロールには、このような特定のイベントを発生させるユーザー操作が組み込まれています。 たとえば、CheckButton ではボックスをクリックすると ValueChanged イベントと ValueFinished イベントが発生し、value プロパティも変わります。 詳細は、『API リファレンス マニュアル』で各コントロールのセクションを参照してください。

ダイナミック イベント ハンドラ

Control の各インスタンスを作成するときにインスタンスのイベント ハンドラを記述して、インスタンスで発生するイベントに応答して実行することができます。 このようなイベント ハンドラは、
ダイナミック イベント ハンドラ と呼ばれ、on 式を使ってオブジェクトにアタッチするのが最も一般的です。 EventTarget.add-event-handler を呼び出してダイナミック イベント ハンドラを EventTarget にアタッチすることもできます。 『API リファレンス マニュアル』の各 Control のセクションで、発生するイベントの詳細を確認してください。
コントロールで発生するイベント以外に、コントロール コンテナで発生するイベントがあります。
イベントおよびイベント処理の詳細については、「イベント」の章も参照してください。 GuiEvent.consume メソッドの使用に関する説明に特に注意してください。このメソッドにより、追加の変更ハンドラによって処理したり再発生させなければならないイベントをターゲットが消費することができます。
次の例は、ValueChanged イベントのダイナミック ハンドラを追加したチェック ボタンを示しています。 ボタンをクリックすると、ボタンで ValueChanged イベントが発生するのを確認してみてください。 さらに、ダイナミック イベント ハンドラによりボタンのラベルが変わります。

例: ダイナミック ValueChanged ハンドラのアタッチされたチェック ボタン
{let my-value:Dynamic =
    {Dynamic "My initial value is false"}
}
{CheckButton
    value = false, || initially unchecked
    label = my-value, || this label will be updated dynamically
    {on ValueChanged at cb:CheckButton do
        {
            set my-value.value = "My current value is " & cb.value
        }
    }
}

スタティック イベント ハンドラ

ダイアログとコントロールは GuiEventTarget クラスも継承していることから、特別なスタティック イベント ハンドラ メソッドを備えています。このメソッドは、任意のクラスで標準イベントの 1 つが発生したときに、そのすべてのオブジェクトで既定の応答を提供するものです。 詳細は「スタティック イベント ハンドラ」のセクションで解説しています。 以下の点に注意してください。
すべての Control に関連する主なスタティック イベント ハンドラの一部を次に示します。 特定のタイプのコントロールすべてについて異なる既定の動作を定義する場合は、そのコントロール クラスのサブクラスを作成し、1 つ以上のスタティック イベント ハンドラの動作をオーバーライドする新しいメソッドを記述してから、そのサブクラスを使ってコントロールを作成します。 「既存のコントロールの変更」のセクションで使用例を参照してください。
次のセクションでは、Dialog 内のコントロールおよびそれ自体で発生する Commit イベントについて説明します。

Commit イベント

ダイアログの利点の 1 つは、ユーザーの選択内容すべてを 1 つのユーザー操作、つまりボタン クリックで収集できる機能にあります。 Curl 言語には、組み込みの [OK] ボタンを備えたモーダル ダイアログを作成するショートカット プロシージャがあります。 ユーザーがこのボタンをクリックすると、すべてのコントロールおよびダイアログ自体で Commit イベントが発生します。 さらにポップアップ ダイアログの場合は、[OK] ボタンによりダイアログを閉じるというメッセージをダイアログに送ります。
ただし、Curl 言語が提供するモーダル ダイアログを使用しない場合は、独自の [OK] または [適用] ボタンを作成して同じ操作を実行することができます。 次のセクションでは、これらのボタンの実装に関して Commit イベントがどのように使用されるかについて説明します。

[OK][適用] および [キャンセル] ボタンの作成

[OK] ボタンの実装方法は次のとおりです。
  1. CommandButton を作成します。
  2. 最初の Action イベントに対するボタンのイベント ハンドラでは、[OK]/[適用] ボタンを含む DialogDialog.commit を呼び出します。
    Dialog.commit は、まずダイアログ内のすべてのコントロールで、次にダイアログ自体で Commit イベントを発生させます。 この後さまざまなコントロールの on-commit イベント ハンドラが実行されてから、それらを含むダイアログの on-commit イベント ハンドラが実行されます。
  3. ボタンの Commit イベントのイベント ハンドラでは、可能な場合に Dialog.close を呼び出してダイアログを閉じます。
[適用] ボタンを含むダイアログを作成することもできます。 [適用] ボタンの実装は、最後のステップを除いて [OK] ボタンと同じです。 つまり、Dialog.close呼び出されず、したがってポップアップ ダイアログの場合でも閉じません。
popup-message プロシージャで生成されるダイアログなどには、オプションで [キャンセル] ボタンを含めることができます。 [キャンセル] ボタンの実装方法は次のとおりです。
  1. CommandButton を作成します。
  2. ボタンの Action イベントのイベント ハンドラでは、ボタンを含む DialogDialog.close を呼び出します。
    この場合、Commit イベントは発生せず、on-commit ハンドラは実行されません。
次の例では、Dialog.commit メソッドがどのように使用されているかを示しています。このメソッドでは、最初にダイアログに含まれるすべての Control で、続いて Dialog 自体で Commit イベントが発生します。

例: Dialog.commit メソッドの使用
{define-proc
    {order-coffee milk?:bool, coffee-type:String}:void
    {popup-message
        {if milk? then
            {text Here is some {value coffee-type} with milk!}
         else
            {text Sorry, no milk with your {value coffee-type}!}
        }
    }
}
{value
    let milk?:bool = true
    let coffee-type:String = "Kenyan"
    let b:CommandButton =
        {CommandButton
            label = "Show non-modal dialog"
        }
    || construct the dialog
    let rf:RadioFrame =
        {radio-buttons
            "Kenyan",
            "Arabica",
            "Sumatran",
            value = "Kenyan"
        }
    let cb:CheckButton =
        {CheckButton
            label = "with milk?"}
    let ok:CommandButton =
        {CommandButton
            label = "OK",
            {on Action do
                {ok.dialog.commit}
                {ok.dialog.close Dialog.ok}
            }
        }
    let cancel:CommandButton =
        {CommandButton
            label = "Cancel",
            {on Action do
                {cancel.dialog.close Dialog.cancel}

            }
        }
    let dialog:Dialog =
        {Dialog
            {spaced-vbox
                rf,
                cb,
                {spaced-hbox ok, cancel}
            },
            {on com:Commit do
                set milk? = cb.value
                set coffee-type = rf.value
                {order-coffee milk?, coffee-type}
                {com.consume}
            },
            {on WindowClose do
                set b.enabled? = true
            }
        }
    {b.add-event-handler
        {on Action at b:CommandButton do
            let v:#View = {b.get-view}
            {unless dialog.open? do
                set b.enabled? = false
                {dialog.show modal? = false, owner = v}
            }
        }
    }
    {value b}
}