行と列はソース
RecordSet のレコードとフィールドに対応しています。
RecordGridColumn で列を明示的に作成して、列の外観と機能を制御するプロパティを設定できます。列は自動的に作成することもできます。列をカスタマイズする場合は、列を自分で追加します。
RecordGrid には充実した機能が既定で含まれています。例を使用して以下の機能を確認してみましょう。
さらに、グリッド セルを右クリックすると、コンテキスト メニューが表示され、以下の選択肢を選択できます。
- コピー: レコード グリッドの選択された領域をクリップボードに文字列としてコピーします。
RecordGrid 内のテキスト データをクリップボードから他のアプリケーションに貼り付けることができます。
- 貼り付け : クリップボードの内容をレコード グリッドの選択された領域に貼り付けます。他のアプリケーションからテキストをコピーして、
RecordGrid に貼り付けることができます。
- フレーム/列/行の固定、固定の解除 : 表示領域の一部をスクロールしないように固定します。残りの表示領域はスクロールできます。[列の固定] を適用すると、現在の列とその左側にあるすべての列が固定されます。[行の固定] を適用すると、現在の行とその上にあるすべての行が固定されます。[フレームの固定] を適用すると、現在のセルより左側にあるすべての列と現在のセルより上にあるすべての行が固定されます。[固定の解除] をクリックすると、領域の固定が解除されます。
- [昇順ソート] および [降順ソート] は、グリッド セルを含む列の値に基づいてレコードをソートします。
- [フィルタの追加] は、次の選択肢を含むサブメニューを開きます。
- [(セルの値) のみ] は、この列で選択されているセルと同じ値を持つレコードのみを表示します。
- [(セルの値) 以上] は、この列で選択されているセルと同じ値またはそれ以上の値を持つレコードのみを表示します。
- [(セルの値) 以下] は、この列で選択されているセルと同じ値またはそれ以下の値を持つレコードのみを表示します。
- [(セルの値) 以外] は、この列で選択されているセルと同じ値を持たないレコードのみを表示します。
- [フィルタを取り除く] は、現在適用されているすべてのフィルタを削除します。
- [変更をコミットする] は、データに加えた変更をソース
RecordSet に永久に保存し、以前の値を破棄します。
- [変更を元に戻す] は、最後のコミット後に行われた変更を破棄して、元の値に戻します。
[フィルタの追加] メニューは、カーソルが
RecordGrid のセルの上にある場合のみ使用できます。
[昇順ソート] と
[降順ソート] コマンドは、カーソルが列の上にある場合に使用できます。
[フィルタを取り除く]、
[変更をコミット]、および
[変更を元に戻す] コマンドは、カーソルが
RecordGrid 内にある場合に使用できます。
| 例:
RecordGrid の既定の動作 |
 |
{include "../../default/support/data-long.scurl"}
{RecordGrid
record-source = records,
height = 10cm,
width = 13cm
}
| |
RecordGrid には、次のようなグリッドの外観を変更するためのオプションが多数用意されています。
次の例では、これらのプロパティを既定値以外の値に設定して
RecordGrid の外観を変更しています。
| 例:
RecordGrid の外観の変更 |
 |
{let people:RecordSet =
{RecordSet
{RecordFields
{RecordField "First", domain = String},
{RecordField "Last", domain = String},
{RecordField "Age", domain = int}
},
{RecordData First = "John", Last = "Smith", Age = 25},
{RecordData First = "Jane", Last = "Smith", Age = 29},
{RecordData First = "Jane", Last = "Jones", Age = 28}
}
}
{value
{RecordGrid
record-source = people,
height = 3cm,
display-column-headers? = false,
display-filler-column? = true,
alternate-row-background = "#cceecc",
grid-line-color = "#ccccff",
horizontal-grid-line-width = 2px,
vertical-grid-line-width = 4px
}
}
| |
RecordGrid.row-background-spec プロパティを使用して、各行の背景色を計算するプロシージャを指定することができます。プロシージャはレコード グリッド、表示されるレコード、および
RecordGrid.records のレコードのインデックスを受け取ります。プロシージャはこの情報に基づいて背景を計算します。プロシージャは頻繁に呼び出される可能性があり、したがってこのプロシージャでの冗長な計算はパフォーマンスに影響を与える可能性があることに注意してください。
次の例では、指定されたレコードのデータに基づいて行の背景を計算します。Notified? フィールドの値が true のレコードの背景は銀色です。この場合、背景色はレコードのグリッド内での位置とは無関係です。
| 例:
データドリブン型の行の背景 |
 |
{include "../../default/support/data-long.scurl"}
{define-proc public {notified rg:RecordGrid, r:Record, i:int}:#Background
{if {r.compare-field "Notified?", true} == 0 then
{return {Background.from-string "silver"}}
else
{return null}
}
}
{RecordGrid
record-source = records,
height = 10cm,
width = 13cm,
row-background-spec = notified
}
| |
次の例では、レコード インデックスを使用して、グリッドに表示される 5 および 10 レコードごとに色づけされた背景を返します。背景は完全に位置に依存していて、レコードのデータとは無関係です。
| 例:
位置に基づいたの行の背景 |
 |
{include "../../default/support/data-long.scurl"}
{define-proc public {notified rg:RecordGrid, r:Record, i:int}:#Background
{if ((i + 1) mod 10) == 0 then
{return {Background.from-string "#ccccff"}}
elseif ((i + 1) mod 5) == 0 then
{return {Background.from-string "#eeeeff"}}
else
{return null}
}
}
{RecordGrid
record-source = records,
height = 10cm,
width = 13cm,
row-background-spec = notified
}
| |
また、レコード グリッドの
key-spec プロパティを一意のフィールド
ID に設定しています。
key-spec を設定すると、レコードのソートなどの一括変更を行っても、レコード グリッドで現在のレコードを保持できます。レコードを選択し、いずれかの列見出しをクリックしてレコードをソートしてください。グリッドの左端にある矢印が、レコードのソート後もレコードとの関連付けを保持していることに注意してください。次の行をコメントにして、例を実行してみてください。
key-spec = "id", ソートを実行すると、矢印がグリッドの先頭のレコードに移動します。
| 例:
見出し行のカスタマイズ |
 |
{let staff:RecordSet =
{evaluate
{url "../../default/support/data.scurl"}
}
}
{let gradient-header:RecordGridRowOptions =
{RecordGridRowOptions
background =
{LinearGradientFillPattern
{Fraction2d 0, 1},
{Fraction2d 0, 0},
{Spectrum.from-endpoints
{FillPattern.get-silver},
{FillPattern.get-white}
}
},
valign = "origin",
halign = "left",
control-actuator-color = "gray",
color = "gray",
font-size = 14pt,
font-family = "serif"
}
}
{let rg:RecordGrid =
{RecordGrid height = 10cm,
record-source = staff,
column-movable?= false,
header-options = gradient-header,
key-spec = "id",
width = 16cm
}
}
{value rg}
| |
次の例では、カスタム列を作成して、基本データにある 2 つのフィールドのデータを 1 列に表示します。
automatic-columns? を
false に設定して列が自動生成されないようにし、
RecordGrid.format-spec を、データ セットから姓と名の両方を含む単一の文字列を返すプロシージャに設定しています。また、この例では年齢の列を明示的に作成する必要があります。
| 例:
2 つのフィールドを 1 列に表示 |
 |
{let people:RecordSet =
{RecordSet
{RecordFields
{RecordField
"First", caption = "First Name", domain = String
},
{RecordField
"Last", caption = "Last Name", domain = String
},
{RecordField "Age", domain = int}
},
{RecordData First = "John", Last = "Smith", Age = 25},
{RecordData First = "Jane", Last = "Smith", Age = 29},
{RecordData First = "Jane", Last = "Jones", Age = 28}
}
}
{let rg:RecordGrid =
{RecordGrid
record-source = people,
height = 3cm,
automatic-columns? = false,
{RecordGridColumn
"First",
editable? = false,
format-spec =
{proc {data:any, r:Record}:String
{return r["First"] & " "&
r["Last"]}
},
header-spec = "Full Name"
},
{RecordGridColumn "Age"}
}
}
{let rg-real:RecordGrid =
{RecordGrid
record-source = people,
height = 3cm
}
}
{value rg}
| |
また、1 列おきに適用する背景色を設定しています。ドラッグ操作で列の順序を変えることができないように、
RecordGrid の
column-movable? オプションは false に設定されていることにも注目してください。
| 例:
カスタム列見出しの作成 |
 |
{let staff:RecordSet =
{evaluate
{url "../../default/support/data.scurl"}
}
}
{define-proc public {make-header rgc:RecordGridColumn}:Graphic
{return
{TextFlowBox
font-weight = "bold",
font-size = 12pt,
color = "green",
rgc.field.caption
}
}
}
{let rg:RecordGrid =
{RecordGrid height = 10cm,
record-source = staff,
width = 16cm,
column-movable? = false,
header-spec = make-header
}
}
{for i:int = 0 to rg.columns.size - 1 do
{if (i mod 2 == 0) then
set rg.columns[i].background = "#cceecc"
}
}
{value rg}
| |
グループ内で列をドラッグアンドドロップできますが、列をグループにドラッグしたり、グループから列をドラッグしたりすることはできません。また、グループそのものをドラッグアンドドロップすることもできません。
グループは、[フレームの固定] 操作に影響します。フレームの固定は、グループの境界でのみ有効です。グループ内の任意の位置で [フレームの固定] を適用すると、固定の境界はグループの右端になります。
| 例:
RecordGrid 列のグループ化 |
 |
{RecordGrid
record-source =
{evaluate
{url "../../default/support/data.scurl"}
},
height = 10cm,
width = 13cm,
{RecordGridColumn "id"},
{RecordGridColumnGroup
"Name",
|| コメントを削除してヘッダーのセパレーターを削除します
||-- enclose-header-label? = false,
{RecordGridColumn "First"},
{RecordGridColumn "Last"}
},
{RecordGridColumnGroup
"Address",
|| コメントを削除してヘッダーのセパレーターを削除します
||-- enclose-header-label? = false,
{RecordGridColumn "City"},
{RecordGridColumn "State"}
}
}
| |
これらのオプションを既定値以外の値に設定する例を次に示します。その結果、グリッドはユーザー操作に反応を示さないことが多くなります。これらのプロパティ設定をさまざまに組み合わせて例を実行し、グリッドの動作を確認してください。
| 例:
UI 動作の変更 |
 |
{let people:RecordSet =
{RecordSet
{RecordFields
{RecordField "First", domain = String},
{RecordField "Last", domain = String},
{RecordField "Age", domain = int}
},
{RecordData First = "John", Last = "Smith", Age = 25},
{RecordData First = "Jane", Last = "Smith", Age = 29},
{RecordData First = "Jane", Last = "Jones", Age = 28}
}
}
{value
{RecordGrid
cells-take-focus? = false,
column-movable? = false,
column-resizable? = false,
editable? = false,
display-record-selectors? = false,
display-navigation-panel? = false,
record-source = people,
height = 3cm
}
}
| |
| 例:
parse-spec の使用 |
 |
{let urls:RecordSet =
{RecordSet
{RecordFields
{RecordField
"Company", domain = String
},
{RecordField
"URL", domain = String
}
},
{RecordData Company = "Curl", URL = "http://www.curl.com"},
{RecordData Company = "Google", URL = "http://www.google.com"},
{RecordData Company = "EBay", URL = "http://www.ebay.com"}
}
}
{let rg:RecordGrid =
{RecordGrid
record-source = urls,
height = 3cm,
automatic-columns? = false,
{RecordGridColumn "Company"},
{RecordGridColumn "URL",
width = {make-elastic},
parse-spec =
{proc {v:String, r:Record}:any
let nv:String =
{if {v.prefix? "http://www."} then v
else "http://www." & v
}
{return nv}
}
}
}
}
{value
{VBox
rg,
{HBox
{CommandButton
width = {make-elastic}, label = "append record",
{on Action do
{urls.append {RecordData}}
}
},
{CommandButton
width = {make-elastic}, label = "commit records",
bound-command = {rg.get-command "commit"}
},
{CommandButton
width = {make-elastic}, label = "revert records",
bound-command = {rg.get-command "revert"}
}
}
}
}
| |
RecordGrid には、フレームの固定機能が用意されています。この機能を使用すると、指定した数の行と列をスクロールできないように設定できます。
RecordGrid の次のプロパティとメソッドは、スクロールしない行と列の数を管理します。
オフセット値では、上側と左側のスクロールして見えなくなる行と列で固定領域を指定できます。
| 例:
見出し行の固定 |
 |
{let staff:CsvRecordSet =
{CsvRecordSet
{url "../../default/support/data.csv"}
}
}
{let rg:RecordGrid =
{RecordGrid
record-source = staff,
display-column-headers? = false,
display-record-selectors? = false
}
}
{rg.set-frozen-region 1, 1}
{value rg}
| |
ソートとフィルタの操作性を変更するには、セルまたは列見出しを右クリックし、表示されるコンテキスト メニューから項目を選択します。
RecordGrid.filter-menu-proc プロパティを使用すると、このメニューをカスタマイズできます。次の例は、メニューの項目の順序を逆にする単純な
filter-menu-proc を示しています。
| 例:
RecordGrid.filter および
RecordGrid.sort の使用 |
 |
{let staff:RecordSet =
{evaluate
{url "../../default/support/data.scurl"}
}
}
{let rg:RecordGrid =
{RecordGrid
record-source = staff, height = 5cm, width = 16cm,
column-selection-enabled? = true,
filter-menu-proc =
{proc {array:{Array-of MenuItem}, cell:RecordGridCell}:{Array-of MenuItem}
{array.reverse}
{return array}
}
}
}
{VBox
rg,
{HBox
{CommandButton label = "Sort by City, State",
width = {make-elastic},
{on Action do
set rg.sort = "City, State"
}
},
{CommandButton
width = {make-elastic},
label = "Filter for Cambridge, MA",
{on Action do
set rg.filter =
{RecordData City = "Cambridge", State = "MA"}
}
}
}
}
| |
| 例:
列の削除と復元 |
 |
{let staff:RecordSet =
{evaluate
{url "../../default/support/data.scurl"}
}
}
{let rg:RecordGrid =
{RecordGrid
record-source = staff, height = 5cm, width = 16cm,
column-selection-enabled? = true
}
}
{let original-columns:{Array-of RecordGridColumn} = {rg.columns.clone}}
{VBox
rg,
{HBox
{CommandButton label = "Remove Selected Column(s)", width = 8cm,
{on Action do
{let new-columns:{Array-of RecordGridColumn} = {rg.columns.clone}}
{for col:RecordGridColumn in rg.selection.columns do
{new-columns.remove {new-columns.find col}}
}
set rg.columns = new-columns
}
},
{CommandButton label = "Restore Original Columns", width = 8cm,
{on Action do
set rg.columns = original-columns
}
}
}
}
| |
次のプロパティは、さまざまな種類の選択を可能にします。
| 例:
RecordGrid による列とレコードの選択 |
 |
{let staff:RecordSet =
{evaluate
{url "../../default/support/data.scurl"}
}
}
{let rg:RecordGrid =
{RecordGrid height = 10cm,
column-selection-enabled? = true,
select-current-record? = true,
cells-take-focus? = false,
record-source = staff,
width = 16cm
}
}
{let msg:VBox = {VBox}}
{VBox
rg,
{HBox
{CommandButton
width = 8cm,
label = "Process records",
{on Action do
{if rg.selection.record-count == 0 then
{popup-message "No records selected"}
else
{for i:int in rg.selection.records do
let r:Record = rg.records[i]
{msg.add {format "%s %s",
r["First"],
r["Last"]
}
}
}
{popup-message
msg
}
{msg.clear}
}
}
},
{CommandButton
width = 8cm,
label = "Process columns",
{on Action do
{if rg.selection.column-count == 0 then
{popup-message "No columns selected"}
else
{for c:RecordGridColumn in rg.selection.columns do
{msg.add c.field.name}
}
{popup-message
msg
}
{msg.clear}
}
}
}
}
}
| |
| 例:
RecordGrid での領域の選択 |
 |
{let staff:RecordSet =
{evaluate
{url "../../default/support/data.scurl"}
}
}
{let rg:RecordGrid =
{RecordGrid height = 10cm,
region-selection-enabled? = true,
record-selection-enabled? = false,
record-source = staff,
width = 16cm
}
}
{let msg:VBox = {VBox}}
{VBox
rg,
{HBox
{CommandButton
width = {make-elastic},
label = "Process regions",
{on Action do
{if rg.selection.region-count == 0 then
{popup-message "No regions selected"}
else
{msg.add "regions: " & rg.selection.region-count}
{for r:RecordGridRegion in rg.selection.regions do
{msg.add "columns: " & r.column-count
& " First column index: " & r.first-column}
{msg.add "rows: " & r.row-count
& " First row index: " & r.first-row}
{msg.add "---"}
}
{popup-message
msg
}
{msg.clear}
}
}
}
}
}
| |
標準の UI では、これらのコマンドには標準のキーボード アクセラレータ (たとえば、コピーの場合は Ctrl + C) または右クリックで表示されるコンテキスト メニューを使用してアクセスできます。
選択、コピー、および貼り付けコマンドは、グリッドに表示されている行と列に対して機能します。フィルタを適用するか列をグリッドから削除した場合は、グリッドに表示されたまま残っているフィールドとレコードに対してのみ機能します。
次の例では、これらのコマンドの使用方法を示しています。次の点に注意してください。
- select-nothing、
copy、および
paste コマンドは、アクティブな選択がない場合は無効になります。
- select-all は、グリッドの内容全体を選択します。
- select-nothing は、選択されているすべての列、行、または領域の選択を解除します。
- Select Region および
Deselect Region というコマンド ボタンは、
RecordGridRegion.default で作成された
fixed-region に対して機能します。
- select-nothing、
copy、および
paste コマンドは、複数の領域が選択されている場合は無効になります。
- この例では、1 つの領域しか選択できません。
region-selection-enabled? = true の行を削除して、この例を実行してみてください。グリッドで選択が不可能になり、
select-all コマンドが無効になります。
| 例:
選択、コピー、貼り付け |
 |
{let staff:RecordSet =
{evaluate
{url "../../default/support/data.scurl"}
}
}
{let rg:RecordGrid =
{RecordGrid height = 10cm,
region-selection-enabled? = true,
record-selection-enabled? = false,
select-current-record? = true,
cells-take-focus? = false,
record-source = staff,
width = 16cm
}
}
{let msg:VBox = {VBox}}
{let fixed-region:RecordGridRegion =
{RecordGridRegion
1, 1, 2, 2
}
}
{VBox
rg,
{HBox
{CommandButton
width = {make-elastic},
label = "Select All",
bound-command = {rg.get-command "select-all"}
},
{CommandButton
width = {make-elastic},
label = "Select Nothing",
bound-command = {rg.get-command "select-nothing"}
},
{CommandButton
width = {make-elastic},
label = "Select Region",
{on Action do
{rg.select-region fixed-region, additive? = true}
}
},
{CommandButton
width = {make-elastic},
label = "Deselect Region",
{on Action do
{rg.deselect-region fixed-region}
}
},
{CommandButton
width = {make-elastic},
label = "Copy Selection",
bound-command = {rg.get-command "copy"}
},
{CommandButton
width = {make-elastic},
label = "Paste",
bound-command = {rg.get-command "paste"}
}
}
}
| |
次の例では