ダイアログの使用

移動

Curl® 言語で記述されたアプレット内では、ユーザーは TAB キーを使用してコントロールとリンクの間を移動することができます。また、SHIFT+TAB を使用して逆の向きに移動することもできます。
移動メカニズムは ActiveTraversor および ActiveTraversalContainer クラスによって実装されます。ActiveTraversor は、TAB を使って移動できるグラフィカル オブジェクトまたは可視オブジェクトで、ActiveTraversalContainer はそうしたオブジェクトのコンテナです。
ActiveTraversorActiveTraversalContainer は抽象クラスです。StandardActiveTraversorStandardActiveTraversalContainer は Curl が提供する具象クラスです。
もっとも一般的な ActiveTraversor はコントロールとリンクで、もっとも一般的な ActiveTraversalContainerDialog です。DialogActiveTraversor でもあることに注意してください。次の図では、クラス階層について説明しています。
ActiveTraversalContainer

StandardActiveTraversalContainer
GraphicOptions GuiEventTarget




ControlContainer


Dialog


移動は Dialog を介して行うのがもっとも一般的なので、機能の多くが ActiveTraversalContainer のすべてに共通するものであるとしても、このセクションの他の部分では移動を Dialog のために実装されたものとして説明します。
ユーザーが ActiveTraversor のタブをクリックすると、ActiveTraversoractive になります。アクティブな ActiveTraversor に必ずしもフォーカスがあるとは限りません。これは、Dialog.current-active プロパティの設定により、各 ActiveTraversalContainer がアクティブな ActiveTraversor を最高で 1 つ持つためです。ダイアログがフォーカスを取得すると、そのアクティブな ActiveTraversor もフォーカスを取得します。
たとえば、ユーザーが ALT-TAB で他のウィンドウに移動する場合、前のウインドウのアクティブな ActiveTraversor はフォーカスがないときでもアクティブなままです。そのウィンドウがフォーカスを再取得すると、その ActiveTraversor もフォーカスを再び取得します。
プログラムを使用して、ダイアログは ActiveTraversor.become-active を呼び出すことにより ActiveTraversor をアクティブにしようと試みます。 ActiveTraversor は可能であればアクティブになります。 コンテナの次または前の ActiveTraversor をアクティブ化させるには、ActiveTraversalContainer.traverse メソッドを使うことができます。 これらの両方のメソッドからは操作が成功したかを意味するブール値がリターンされます。 ActiveTraversor がアクティブにならない場合、その親を通して次の ActiveTraversor で試行します。
アクティブにならない ActiveTraversor (および通常、タブでスキップされる ActiveTraversor) は次の ActiveTraversor です。
ActiveTraversor は、その ActiveTraversalContainer に存在を通知し、ActiveTraversalContainerActiveTraversor を登録するようにするためのメカニズムとして非ローカル オプション active-traversal-container を使用します。
ダイアログはその最新の (登録済み) ActiveTraversor のリストを保持しています。ActiveTraversor のタブの順序は、各 ActiveTraversorActiveTraversor.tab-index 値によって変わります。既定では、tab-index0 の値を持っています。
ActiveTraversor は、タブ インデックス値が 0 であるものを除き、値を増加させるとタブが前に進みます。それらは最終のタブになります。同じインデックス値を持つ ActiveTraversor のタブは、親の定義した順序になります。たとえば、VBox 内では、トップレベル オブジェクトの既定のタブ順は (オブジェクトが同じタブ インデックスの場合) トップからボトムです。
明示的に ActiveTraversor のタブ順を設定し、ダイアログ内でのタブ順を変更することができます
ActiveTraversalContainer はそれ自体が ActiveTraversor なので、ActiveTraversalContainer 内のダイアログにもタブ インデックスがあります。
ローカル プロパティ Dialog.repeat-traversal? が TRUE の場合、タブの順序はダイアログの初めにループします。既定値が FALSE の場合、タブを移動すると親 ActiveTraversalContainer の次の ActiveTraversor へ進みます。
次の例では、コントロールとリンクのあるダイアログについて説明します。

例: ダイアログ内のコントロールとリンク
{let command:CommandButton={CommandButton}}
{let command2:CommandButton={CommandButton label="CommandButton2"}}
{let check:CheckButton={CheckButton}}
{let textf:TextField={TextField width=1in, prompt="TextField"}}

{set command.tab-index = 3}
{set command2.tab-index = 1}
{set textf.tab-index = 2}

{let dialog:Dialog=
    {Dialog
        repeat-traversal?=true,
        {spaced-hbox
            margin=0.25cm,
            command,
            command2,
            check,
            textf,
            {link href={url "dialogs-working.curl"}, Top of Page}
        }
    }
}
{let tfb:TextFlowBox = {TextFlowBox "Tab index values: "}}
{for control:Control in dialog.controls do
    {tfb.add control.tab-index}
    {tfb.add " "}
}

{VBox
    dialog, tfb
}
次の例では、GroupBox を使って、前例のコントロールをグループ化します。 tab を使ってコントロール間を移動します。 GroupBox 内のコントロールはフォーカスを取得しますが、 GroupBox 自体はフォーカスを受け取らないことに留意してください。 GroupBox.tab-index の値により、 Buttons とラベルの付くグループの前に、 Boxes とラベルの付くグループにナビゲートされることにも留意してください。

例: GroupBox を使ってコントロールをグループ化
{let command:CommandButton={CommandButton}}
{let command2:CommandButton={CommandButton label="CommandButton2"}}
{let check:CheckButton={CheckButton}}
{let textf:TextField={TextField width=1in, prompt="TextField"}}

{set command.tab-index = 3}
{set command2.tab-index = 1}
{set textf.tab-index = 2}

{Dialog
    repeat-traversal?=true,
    {spaced-hbox
        margin=0.25cm,
        {GroupBox
            label = "Buttons",
            tab-index = 5,
            {spaced-hbox
                command,
                command2
            }
        },
        {GroupBox
            label = "Boxes",
            tab-index = 4,
            {spaced-hbox
                check,
                textf
            }
        },
        {link href={url "dialogs-working.curl"}, Top of Page}
    }
}
ダイアログ内では、ユーザーはタブの順序で、ある Control から他へ移動することができます。たいていの場合、アクティブなコンポーネントはキーボード フォーカスを持っています。つまり、ユーザーが行うすべてのキーボードの動作は、その結果アクティブなコントロールで発生するイベントに変換されます。
次の例では、チェックボタンが become-active をそれ自身に呼び出すことによりプログラム的にアクティブになります。

例: コントロールをプログラム的にアクティブにする
{let textf:TextField={TextField prompt="TextField"}}
{let check:CheckButton={CheckButton}}

{let dialog:Dialog=
    {Dialog
        use-look-and-feel?=false,
        background = "wheat",
        {spaced-vbox
            margin=0.5cm,
            textf,
            check,
            {CommandButton
                label="Close",
                {on Action do
                    {dialog.close "closed"}
                }
            }
        },
        {on DialogShow at dialog:Dialog do
            {check.become-active}
        }
    }
}

{CommandButton
    label = "Show Dialog",
    {on Action do
        {dialog.show}
    }
}

コントロールのキーボード ショートカット

典型的な GUI インターフェースの使用は、マウスを使ってのポイント、クリックのジェスチャーを伴いますが、多くのユーザーは、ポイントやクリックの代わりにキーボード ショートカットを利用することを好みます。ローカル オプションmnemonic では、コントロールにキーボード ショートカットとして動作するキーを定義することが出来ます。このオプションは、ActiveTraversor 上で定義されます。したがって、多くのコントロールを含むそのサブクラスの全てで利用することが出来ます。Label クラスを使用するコントロールは、Label.mnemonic を使って、キーボード ショートカットを設定することが出来ます。
キーボード ショートカットを動作させる為には、コントロールは、ActiveTraversalContainerに含まれていなければなりません。ブラウザ上で実行されるアプレットは、自動的に ActiveTraversalContainer でラップされますが、View 内のコントロールは、DialogTabPane のようなコンテナ内に収める必要があります。
ラベル文字列が、ニーモニック マーカー文字'&'を含んでいる場合、Label を持ったコントロールは、mark-mnemonic を使用します。このアプローチは、コントロールにキーボード ショートカットを設定するもっともシンプルな方法です。以下のサンプルは、ニーモニック マーカー文字を使って、キーボード ショートカットを設定しています。ショートカットを使うには、ニーモニックを活性化させるキーAltをニーモニック キーと一緒に押してください。例えば、Alt-o のようにです。

例: ラベル テキスト内のニーモニックの設定
{let rf:RadioFrame =
    {RadioFrame
        {spaced-vbox width=4cm,
            {bold Radio Buttons},
            {RadioButton
                label = "&One"
            },
            {RadioButton
                label = "&Two",
                radio-value = "2"
            },
            {RadioButton
                label = "T&hree",
                radio-value = "3"
            }
        }
    }
}
{Dialog
    margin = 0.25cm,
    {spaced-hbox
        {spaced-vbox
            rf,
            {bold Command Button},
            {CommandButton
                label = "Show &value of selected Radio Button",
                mnemonic = 'V',
                {on Action do
                    {popup-message
                        {spaced-vbox
                            {format
                                "RadioFrame's Value: %s", rf.value}
                        }
                    }
                }
            }
        }
    }
}
GroupBox ラベルを使用して、フォーカスを取らない時でもボックスにキーボード ショートカットを作成することが出来ます。フォーカスは、以下のサンプルで表されているように、タブ順で最初のグループボックス内のコントロールに入ります。このサンプルは、次のサンプルとキーボード ショートカット'C'を共有しています。alt-c を押した時に、サンプルが Commands グループボックスを見つけることを確認する為には、サンプル内コントロールをクリックしてください。それはダイアログ内のコントロールにフォーカスを与え、RTEにショートカットを解決する為に最初にそこを見るようにさせます。
同様のキーの組合せがメニュー コマンドをアクティブにするキーボード ショートカットとして使用されていることもあるので注意してください。メニュー アクセス キーとニーモニックを参照してください。メニュー ショートカットがキーボード ショートカットに優先するので、メニュー ショートカットと競合しない文字を選択することが重要です。

例: グループボックスのキーボード ショートカット
{let command1:CommandButton=
    {CommandButton
        label="One",
        tab-index = 3
    }
}
{let command2:CommandButton=
    {CommandButton
        label="Two",
        tab-index = 1
    }
}
{let textf:TextField =
    {TextField
        width=1in,
        tab-index = 2,
        prompt="TextField"}
}
{let check:CheckButton = {CheckButton}}
{Dialog
    repeat-traversal?=true,
    {spaced-hbox
        margin=0.25cm,
        {GroupBox
            label = "&Commands",
            tab-index = 5,
            {spaced-hbox
                command1,
                command2
            }
        },
        {GroupBox
            label = "&Boxes",
            tab-index = 4,
            {spaced-hbox
                check,
                textf
            }
        }
    }
}
Label を作成する時に明示的にニーモニックを記述することが出来ます。このアプローチは、コントロールのラベルが、テキストを含んでいない時に有用です。下線付きのテキストを使って、ユーザーにショートカット キーを示すことは出来ませんが、そのようなショートカットは、特殊な状況で有用である場合があります。以下のサンプルでは、カラー モデルで色を識別する文字が、キーボード ショートカットとして動作し各色の RadioButton を選択します。このダイアログ内で前のサンプルと共用されているキーボード ショートカットalt-c をRTEに解決させる為には、このサンプル内のコントロールをクリックする必要があります。

例: テキストがないラベルのキーボード ショートカット
{Dialog
    margin = 2mm,
    {spaced-vbox
        "RGB: ",
        {RadioFrame
            {HBox
                {RadioButton
                    label =
                        {Label
                            {Frame
                                background = "red",
                                width = 10px,
                                height = 10px
                            },
                            mnemonic = 'r'
                        },
                    style = "command-button-standard"
                },
                {RadioButton
                    label =
                        {Label
                            {Frame
                                background = "green",
                                width = 10px,
                                height = 10px
                            },
                            mnemonic = 'g'
                        },
                    style = "command-button-standard"
                },
                {RadioButton
                    label =
                        {Label
                            {Frame
                                background = "blue",
                                width = 10px,
                                height = 10px
                            },
                            mnemonic = 'b'
                        },
                    style = "command-button-standard"
                }
            }
        },
        "CMYK: ",
        {RadioFrame
            {HBox
                {RadioButton
                    label =
                        {Frame
                            background = "cyan",
                            width = 10px,
                            height = 10px
                        },
                    mnemonic = 'c',
                    style = "command-button-standard"
                },
                {RadioButton
                    label =
                        {Frame
                            background = "magenta",
                            width = 10px,
                            height = 10px
                        },
                    mnemonic = 'm',
                    style = "command-button-standard"
                },
                {RadioButton
                    label =
                        {Frame
                            background = "yellow",
                            width = 10px,
                            height = 10px
                        },
                    mnemonic = 'y',
                    style = "command-button-standard"
                },
                {RadioButton
                    label =
                        {Frame
                            background = "black",
                            width = 10px,
                            height = 10px
                        },
                    mnemonic = 'k',
                    style = "command-button-standard"
                }
            }
        }
    }
}
Label を使用しないコントロールにキーボード ショートカットを作成することが出来ます。しかし、コントロールにニーモニックを設定し、ラベルとして機能する関連付けられたテキスト内の文字に下線を付ける処理を行わなければなりません。

例: ラベルがないコントロールのキーボード ショートカット
{let listbox:ListBox =
    {ListBox
        height = 1.0in,
        mnemonic = 'a',
        "Aardvark", "Cat", "Dog", "Elephant", "Gnu", "Zebra"
    }
}
{let listbox1:ListBox =
    {ListBox
        height = 1.0in,
        mnemonic = 'n',
        "One", "Two", "Three", "Four", "Five", "Six"
    }
}
{Dialog
    margin = 2mm,
    {HBox
        {text {underline A}nimals: },
        listbox,
        {text {underline N}umbers: },
        listbox1
    }
}
TabPane は、Label を持っているので、ユーザーがタブ ペインを選択するのを助ける為にキーボード ショートカットを使うことが出来ます。

例: タブ ペインのキーボード ショートカット
{TabContainer
    width = 3cm,
    height = 3cm,
    {TabPane
        label = "Tab &X",
        tab-button-tooltip = "first tab",
        {TextFlowBox
            margin = 5pt,
            font-weight = "bold",
            font-size = 28pt,
            "-X-"
        }
    },
    {TabPane
        label = "Tab &Y",
        mnemonic = '2',
        tab-button-tooltip = "second tab",
        {TextFlowBox
            margin = 5pt,
            font-weight = "bold",
            font-size = 28pt,
            "-Y-"
        }
    },
    {TabPane
        label = "Tab &Z",
        mnemonic = '3',
        tab-button-tooltip = "third tab",
        {TextFlowBox
            margin = 5pt,
            font-weight = "bold",
            font-size = 28pt,
            "-Z-"
        }
    }
}
同様のキーの組合せがメニュー コマンドをアクティブにするキーボード ショートカットとして使用されていることもあるので注意してください。メニュー ショートカットがキーボード ショートカットに優先するので、メニュー ショートカットと競合しない文字を選択することが重要です。