インタラクティブな web ページやアプリケーションのユーザーは、マウスまたはキーボードを頻繁に使用して選択を行ないます。たとえばショッピング カートにアイテムを追加したり、ファイルを表すアイコンを選択して削除したり、テキストをコピーしてテキスト エディタに貼り付ける場面がこれに含まれます。このような対話をサポートする全体的な機能は、選択(Selection)と呼ばれます。選択の主なタイプは個別選択と範囲選択です。
- 個別選択とは、選択順序に関係しない 1 つまたは複数の項目の選択です。これらの項目は通常、グラフィカル オブジェクトとして表されます。
- 範囲選択は、始点と終点により項目範囲を選択することです。範囲選択の一般的な使用例には、テキストを選択する際にマウスの押し下げによって始点と終点を指定する場合が挙げられます。
Curl の選択構造は次の主要な機能領域、選択コンテキスト、選択およびコマンドで構成されています。
グラフィックスと同様にシェイプも選択に使用できます。
「
シェイプ」 の章の、
「
選択」 を参照してください。
例:
DiscreteGraphicSelectionFrame の使用 |
 |
{value
let triangle:RegularPolygonGraphic =
{RegularPolygonGraphic
graphic-selectable={GraphicSelectable},
height = 2cm,
width = 2cm,
sides = 3
}
let rectangle:RegularPolygonGraphic =
{RegularPolygonGraphic
graphic-selectable={GraphicSelectable},
height = 2cm,
width = 2cm,
sides = 4
}
let pentagon:RegularPolygonGraphic =
{RegularPolygonGraphic
graphic-selectable={GraphicSelectable},
height = 2cm,
width = 2cm,
sides = 5
}
let info-vbox:VBox={VBox}
let cb:CommandButton={CommandButton label="Clear Selections"}
let dgsf:DiscreteGraphicSelectionFrame =
{DiscreteGraphicSelectionFrame
{spaced-hbox
color = {FillPattern.get-blue},
triangle,
rectangle,
pentagon
},
{on sc:SelectionChanged at dgsf:DiscreteGraphicSelectionFrame do
{info-vbox.clear}
set cb.enabled?=not dgsf.selection.empty?
{for s:GraphicSelectable in dgsf.selection.items do
{info-vbox.add
{format
"You have selected a polygon with %d sides. \n",
(s.graphic asa RegularPolygonGraphic).sides
}
}
}
}
}
{cb.add-event-handler
{on Action do
{dgsf.select-nothing}
{info-vbox.clear}
}
}
{spaced-vbox
dgsf,
{center {value cb}},
info-vbox
}
}
| |
ほとんどの Web ページでは、ユーザーがマウスを使用してテキストの選択やコピーができるように範囲選択をサポートしています。範囲選択は、特別なタイプのテキスト選択です。選択への書き込みは許可されていないので、貼り付け操作はできません。
選択中に個々の領域 (コンテキスト) を区別する場合に範囲選択を使用するのが一般的です。たとえば、Web サイトでユーザーがマウスを使って新聞記事のテキストを選択するときに、ページの広告の領域上をマウスが移動してもこの領域が選択範囲から除外されるようにする場合などです。同様に、ユーザーが広告領域内でマウスを押さえると、選択対象が広告の選択コンテキストに限定されるようにする場合もあります。
- GuiRangeSelectionFrame にグラフィック階層をラップします。
- コントロールを使用してその bound-command プロパティを適切なコマンドに設定して、選択項目の選択タスクを実行します。
範囲選択で領域のスコープを定義する例を次に示します。次の点に注意してください。
- サンプル テキストの範囲選択は、テキスト領域まで拡張されません。
- テキスト領域に挿入されるテキストは、右側の CommandButton により "select-all" と "delete" のコマンドで操作されます。
例:
GuiRangeSelectionFrame の使用 |
 |
{value
let grsf:GuiRangeSelectionFrame =
{GuiRangeSelectionFrame
{TextFlowBox
{paragraph font-weight="bold",
Sample Text},
{paragraph
Left
{VBox
vorigin="center",
halign="center",
spacing=8pt,
"Up",
"Down"
}
Right
}
}
}
let text-area:TextArea =
{TextArea
width=3in
}
{spaced-hbox border-width=1px,
border-color="black",
{spaced-vbox
grsf,
{CommandButton
label="Clear Range Selection",
bound-command={grsf.get-command "select-nothing"}
}
},
{VBox
{paragraph font-weight="bold", Text Area},
{paragraph Copy text on the left and paste it below.},
text-area
},
{VBox
height=1in,
{Fill},
{CommandButton
label="Select All Text in Text Area",
bound-command={text-area.get-command "select-all"},
takes-focus?=false
},
{CommandButton
label="Delete Selected Text in Text Area",
bound-command={text-area.get-command "delete"},
takes-focus?=false
}
}
}
}
| |
選択コンテキストでは、選択時に含まれる項目と除外される項目を定義します。たとえば、個別選択アプリケーションでユーザーがデスクトップ アイコンのグループを投げ縄ツールで選択することがあります。このような場合に、実行可能ファイルのアイコンが投げ縄ツールの選択範囲に含まれていても選択から除外するような選択コンテキストを確立することができます。
既定では、すべての
View にはビュー全体で 1 つの範囲選択を確立するトップレベルの範囲選択コンテキストがあります。これは、既定ではアプレットには 1 つの範囲選択コンテキストがあるということを意味します。ただし、たいていの場合は Web ページ内のすべてのアイテムが同じコンテキストに属さないように、ネストされた範囲選択コンテキストを定義します。
たとえば、トップレベルにテキストと画像を持ち、選択コンテキストを指定しない簡単なアプレット(例:「
単純なアプレット」)を作成するとします。 テキストと画像は同じコンテキストに属しています。マウスを使って範囲を選択してみてください。
selection-context は、グラフィカル オブジェクトが属する選択コンテキストを指定するための非ローカル オプションです。グラフィカル オブジェクト自体が
SelectionContext サブクラスである場合、既定でこの非ローカル オプションは通常
self に設定されます。
selection-context は非ローカル オプションなので、この値が設定されていない場合は、グラフィカルな親 (または一番近い祖先) の値を取り、オブジェクトをその親 (または祖先) と同じ選択コンテキストに含めることになります。
ほとんどの場合、選択コンテキストを直接
SelectionContext に設定する必要はないでしょう。代わりに、暗黙的に指定された選択コンテキストからオブジェクトおよびその埋め込み階層を除外するか、またはオブジェクト自体の埋め込み選択コンテキストを確立します。
- グラフィカル オブジェクトの selection-context を null に設定して、埋め込まれているグラフィック階層を周囲のコンテキストから除外します。ただし、この設定により埋め込みグラフィック階層は選択できなくなることに留意してください。
- 埋め込みグラフィック階層自体の選択コンテキストを確立するには、オブジェクト (およびそのグラフィック階層) を DiscreteGraphicSelectionFrame (個別選択)、または GuiRangeSelectionFrame (範囲選択) オブジェクトにラップします。これらのクラスは両方とも SelectionContext のサブクラスです。これらの selection-context オプションは、既定で self に設定されています。
これで、ネストされた選択コンテキストを "埋め込まれた" コンテキスト内に確立できるようになります。
ネストされた選択コンテキストの例を次に示します。
例:
ネストされた選択コンテキスト |
 |
{value
{spaced-hbox
{VBox
{text Outer Selection Context Starts},
{radio-buttons
"Mike Harris",
"Sam Richardson"}
},
{VBox font-style="italic",
selection-context=null,
{text Excluded Hierarchy},
{GuiRangeSelectionFrame
{spaced-vbox color="brown",
{text Inner Selection Context},
{text Part of Inner Selection Context}
}
},
{text End of Excluded Hierarchy}
},
{VBox
{text Still in the outer selection context ...},
{radio-buttons
"Mike Harris",
"Sam Richardson"},
{text Outer Selection Context Ends}
}
}
}
| |
個別選択は通常、クリック可能なグラフィカル オブジェクト (個別グラフィック選択) として実装されます。ユーザーはオブジェクトをクリックするか投げ縄ツールを使用して個別選択を行ないます。次のプロパティは、個別選択をサポートする UI の作成の必要なものです。
GraphicSelectable は、ユーザーによるクリックまたは 四角形選択 (投げ縄) でグラフィックをキャプチャできるかどうかを決定する情報をカプセル化しています。特別な動作を必要としない場合は、グラフィカル オブジェクトを新しい GraphicSelectable のインスタンスに設定するだけ十分です。それ以外の場合は、GraphicSelectable をサブクラス化してメソッドをオーバーライドすることを推奨します。
プロパティを false に設定して複数選択を不可能にする場合もあります。
次の例では、赤、緑、青の個々のグラフィック階層の周囲に DiscreteGraphicSelectionFrame をラップし、直接その上で draw-style を設定できるようにしています。個々の階層にある選択可能な項目をクリックする、または色々なアイテムを各ボックスにドラッグして、それぞれの draw-style 値がどのような結果になるか確かめてみてください。
CTRL+ クリックで選択前の draw-style に戻ります。
描画スタイルを
反転 した際の振る舞いは、どのレンダラーを使用しているかに依存します。
特に、Windows の既定のレンダラーは 色の反転といった能力を持っていないため、クロスハッチ・パターンのオーバーレイを使用するでしょう。
色の反転がアプリケーションに必要な場合は、
set-rendering-mode プロシージャを使用し、
RenderingMode.normal を選択してください。
例:
draw-style の設定 |
 |
{define-proc {dgsf draw-style:GraphicSelectableDrawStyle, border-color:FillPattern}:DiscreteGraphicSelectionFrame
{return
{DiscreteGraphicSelectionFrame
draw-style=draw-style,
{spaced-vbox
margin=0.5cm,
halign="center",
border-width=3pt,
border-color=border-color,
color=border-color,
{small
draw-style\=\"{value draw-style.name}\"},
{image width=1in, height=1in,
graphic-selectable={GraphicSelectable},
source={url "curl://install/docs/default/images/adria.jpg"}},
{EllipseGraphic
graphic-selectable={GraphicSelectable},
width=0.5in, height=0.5in,
fill-color=border-color},
{TextDisplay
graphic-selectable={GraphicSelectable},
value = draw-style.name}
}
}
}
}
{HBox spacing=2cm,
{dgsf "mask", "red"},
{dgsf "invert", "green"},
{dgsf "none", "blue"}
}
| |
このテキスト管理機能によって、テキスト コントロールはそれ自体が選択コンテキストになります。各テキスト コントロール クラスは
WritableTextSelectionContext を継承します。既定では、このようなグラフィカル オブジェクトの
selection-context オプションは
self に設定されていて、周囲のグラフィック階層とは別に選択コンテキストを作成することができます。
テキストコントロールの組み込まれている選択コンテキストの例を次に示します。ここでは selection-context 非ローカル オプションの明示的な設定はありませんが、マウスで範囲選択を行なうと、確立されているいくつかの選択コンテキストを確認することができます。
例:
テキストコントロールの選択コンテキスト |
 |
{spaced-hbox
{spaced-vbox
{text Please Enter Your User Name and Password.},
{Table columns=2,
valign="bottom",
{bold User Name:}, {TextField width=1in},
{bold Password:}, {PasswordField width=1in}
}
},
{spaced-vbox width=3in,
{text Describe the problem you have encountered:},
{TextArea
value="text area text area"
}
}
}
| |
マウスまたはキーボードによって、別の選択コンテキストをアクティベートすることにより、
選択コンテキストの状態が変化することがあります。選択コンテキストは、
非アクティブとして表示される可能性があります。テキストコントロールの場合は、
選択対象自体を落下していまうことがあります。
ボタンのような他のコントロールを使用してテキストコントロール内の選択対象を操作する場合、
テキストコントロールが、非アクティブになり選択内容がクリアされることを最初に回避する必要があります。
そのためには、対象のコントロールの takes-focus? を false に設定します。
次の例でこの方法を示します。
例:
takes-focus? を false に設定 |
 |
{value
let name-tf:TextField = {TextField width=1in}
let t:Table=
{Table columns=2,
valign="bottom",
{bold Name:}, name-tf
}
let ok:CommandButton =
{CommandButton
label="OK"}
let select-all:CommandButton =
{CommandButton
label="Select all text",
bound-command={name-tf.get-command "select-all"},
takes-focus?=false
}
let delete:CommandButton =
{CommandButton
label="Delete selected text",
bound-command={name-tf.get-command "delete"},
takes-focus?=false
}
{spaced-vbox
{text Please enter your name},
t,
{HBox
{Fill},
ok,
select-all,
delete
}
}
}
| |
Curl コントロールとメニュー操作により、一般的な選択タスクをプログラムとして簡単に実行することができます。さらにこれらのコントロールは、現在の選択状態に応じて無効または有効になります。
選択コンテキストは、コマンド アーキテクチャを利用して選択タスクを実行します。
次に、返された Command をコントロールの bound-command プロパティに代入します。
有効なコマンド文字列については、次の表を参照してください。
| 個別選択 | 範囲選択 | テキストの選択 |
"select-all" | Y | Y | Y |
"select-nothing" | Y | Y | Y |
"copy" | N | Y | Y |
"cut" | N | N | Y |
"delete" | N | N | Y |
"paste" | N | N | Y |
"find" | N | Y | N |
例:
select-all および select-nothing の使用 |
 |
{value
let dgsf:DiscreteGraphicSelectionFrame=
{DiscreteGraphicSelectionFrame
{spaced-vbox
{image width=2cm, height=2cm,
source={url "curl://install/docs/default/images/brick-staggered.jpg"},
graphic-selectable={GraphicSelectable}
},
{image width=2cm, height=2cm,
source={url "curl://install/docs/default/images/leaves.jpg"},
graphic-selectable={GraphicSelectable}
}
}
}
let cb-all:CommandButton=
{CommandButton
label="Select All",
bound-command={dgsf.get-command "select-all"}
}
let cb-nothing:CommandButton=
{CommandButton
label="Select Nothing",
bound-command={dgsf.get-command "select-nothing"}
}
{spaced-hbox
dgsf,
{spaced-vbox
cb-all,
cb-nothing
}
}
}
| |
次の例では、TextFlowBox は
GuiRangeSelectionContext のサブクラスである
GuiRangeSelectionFrame にラップされます。[paste] ボタン以外のすべてのコマンド ボタンは TextFlowBox にバインドされ、[paste] ボタンは TextField にバインドされます。ここでは、[paste] コマンドは書き込み可能テキストの選択コンテキストにのみ実装されます。
例:
copy および paste の使用 |
 |
{value
let tf:TextField =
{TextField
value="text field text field."}
let grsf:GuiRangeSelectionFrame=
{GuiRangeSelectionFrame
{TextFlowBox
"Lots of text in a TextFlowBox"
}
}
let cb1a:CommandButton =
{CommandButton
label="Select Text",
bound-command={grsf.get-command "select-all"}
}
let cb1b:CommandButton =
{CommandButton
label="Clear Selection",
bound-command={grsf.get-command "select-nothing"}
}
let cb2:CommandButton =
{CommandButton
label="Copy",
bound-command={grsf.get-command "copy"}
}
let cb3:CommandButton =
{CommandButton
label="Paste in Text Field",
bound-command={tf.get-command "paste"}
}
{HBox
{value grsf},
{VBox
{HBox cb1a, cb1b},
cb2,
cb3
},
{value tf}
}
}
| |
SelectionContext クラスは、選択アーキテクチャで主要な役割を果たします。
SelectionContext は抽象基本クラスです。このサブクラスでは、アーキテクチャがサポートする種々の選択を実装します。
各
SelectionContext のサブクラスは、
Selection オブジェクトを保持します。同様に、
Selection は並列クラス階層の抽象クラスです。各サブクラスは
Selection を 1 つのタイプとして実装します。このタイプは特定のタイプの
SelectionContext によって保持されます。
選択アーキテクチャでの主要なクラスは次のとおりです。
選択において発生するイベントは
SelectionEvent クラス階層に属します。
SelectionContext クラスは、それ自体または対応する
Selection が変更するときにイベントを発生させます。
以下のセクションでは、選択コンテキストと選択クラス階層について説明します。
SelectionContext クラス階層を次に示します。ここで、
SelectionContext はすべて
CommandContext であり、したがって特定の目的に合わせて (選択) コマンドを作成して保存することができます。たとえば、
WritableTextSelectionContext は、他の選択コンテキストではサポートしない "paste" コマンドをサポートします。
SelectionContext は、項目を選択する領域 (コンテキスト) の境界を定義します。コンテキストの外側またはネストされたコンテキスト内の項目は、このコンテキストに存在しません。
すべてのグラフィカル オブジェクトには
selection-context 非ローカル オプションがあります。各オブジェクトの
selection-context オプションの値は、オーバラップしていない、潜在的にネストされた選択コンテキストがどのように区分されるかを示します。
selection-context を設定しない場合、その値は他の非ローカル オプションと同じようにグラフィカルな親になります。
すべてのグラフィック階層のトップレベルには
View があり、これは
GuiRangeSelectionContext を継承します。このトップレベルの
View では、既定により
selection-context 非ローカル オプションを
self に設定します。したがって、下位のグラフィカル オブジェクトの
selection-context が明示的に設定されていない場合はすべて同じ選択コンテキストに属することになります。
SelectionContext はそれぞれ
Selection オブジェクトを持ちます。このオブジェクトには、コンテキストで現在選択されている項目が保持されています。何も選択されていない場合、
Selection は空になります。
SelectionContext.selection メンバ経由で選択にアクセスできます。選択を使用するアプリケーションでは、これを読み取り専用として扱い、将来の有効性に依存しないことを推奨します。むしろ、選択にアクセスしたら直ちにこれを使用して破棄するようにします。
SelectionContext は、以下の状況において現在の
Selection を変更することができます。
SelectionContext はさまざまな
SelectionEvent を発生させて、
Selection が変更したことを他のオブジェクトに通知します。
SelectionContext 自体では次のイベントが発生します。
SelectionContext で発生したイベントのイベント クラス階層を次に示します。
個別グラフィック選択には、ユーザーがグラフィカル オブジェクトを選択したときに選択項目を見ることができるという便利な点があります。
たとえば、マウスのクリックまたは投げ縄ツールでグラフィカル オブジェクトを選択できるアプレットでは、DiscreteGraphicSelectionContext の機能を活用することができます。
この選択を保持するために、追加レベルのイベントが発生します。
- DiscreteSelection でオブジェクトが追加または削除されると、DiscreteSelectionContext は追加または削除された項目で SelectableAdded または SelectableRemoved イベントを発生させてから、それ自体でイベントを発生させます。
- DiscreteGraphicSelectionContext がアクティブな選択コンテキストになるとき、またはアクティブな選択コンテキストでなくなるときに、DiscreteSelection 内の GraphicSelectable オブジェクトをループして各オブジェクトで SelectionContextActivated または SelectionContextDeactivated を発生させ、次にそれ自体でイベントを発生させます。
このセクションの例では、
DiscreteSelection 内の
GraphicSelectable オブジェクトをループする方法を示します。
例:
Selectable 内のループ |
 |
{define-class FoodBook {inherits Frame}
field author:#String
field image:#any
{constructor {default
name:String,
author:#String="",
image:#any=null,
...}
set self.name = name
set self.author = author
set self.image = image
{construct-super self.image, width=1in, height=1in, ...}
}
}
{let book1:FoodBook=
{FoodBook
"Heads-Up Appetite",
author="M. Giraffe",
image={image
source={url "curl://install/docs/default/images/leaves.jpg"}
},
graphic-selectable={GraphicSelectable}
}
}
{let book2:FoodBook=
{FoodBook
"Feeding Near Your Feed",
author="B. Goat",
image={image
source={url "curl://install/docs/default/images/grass.jpg"}
},
graphic-selectable={GraphicSelectable}
}
}
{let info-vbox:VBox={spaced-vbox}}
{let s-c-frame:DiscreteGraphicSelectionFrame=
{DiscreteGraphicSelectionFrame
{spaced-vbox
margin=0.25cm,
book1,
book2
},
{on event:SelectionChanged at s-c:DiscreteGraphicSelectionFrame do
{info-vbox.clear}
{for s:GraphicSelectable in s-c.selection.items do
{info-vbox.add (s.graphic asa FoodBook).author}
}
}
}
}
{set s-c-frame.multiple-selection-enabled? = true}
{spaced-hbox
valign="top",
s-c-frame,
{spaced-vbox
{bold Leaves or Grass for Lunch?},
{CommandButton label="Clear Selections",
bound-command={s-c-frame.get-command "select-nothing"}
},
info-vbox
}
}
| |
Copyright © 1998-2019 SCSK Corporation.
All rights reserved.
Curl, the Curl logo, Surge, and the Surge logo are trademarks of SCSK Corporation.
that are registered in the United States. Surge
Lab, the Surge Lab logo, and the Surge Lab Visual Layout Editor (VLE)
logo are trademarks of SCSK Corporation.