RecordGridPaste を継承してカスタマイズする方法がありそうですね。
セル側だけでハンドリングできると良かったのですが、
少なくとも、この方法ではセル、グリッド、コマンドの3者に処理を記述する必要がありそうです。
Code:
||貼り付けを無視したいセルに対して、継承をする Mixin クラス
{define-class public IgnorePasteCellMixin}
||オープンコントロールから引用
{define-class public open CustomRecordGridPaste {inherits RecordGridPaste}
{constructor public {default context:RecordGrid}
{construct-super context}
}
{method protected open {execute}:void
{if not self.enabled? then {return}}
|| 1) Get the clipboard and ensure its validity
let clipping:String = ""
let clipboard-valid?:bool = false
{try
set (clipping, clipboard-valid?) =
{{Clipboard.get-system-clipboard}.get-string}
catch e:HostClipboardException do
{return}
}
{if not clipboard-valid? then {return}}
|| 2) Setup
let constant grid:RecordGrid = self.context
let constant ui:RecordGridUI = grid.ui
let constant selection:RecordGridSelection = grid.selection
let constant selection-empty?:bool = selection.empty?
let constant line-delimiter:char = '\n'
let constant cell-delimiter:char = '\t'
let constant cell-splitter:CharClass = {CharClass.from-any cell-delimiter}
let column-index:int = -1
let record-index:int = -1
let leftmost-col-index:int = 0
|| 3) Locate our starting cell and leftmost boundary
{if-non-null focus-cell = ui.grid-focus then
{if-non-null column = focus-cell.column then
set column-index = {grid.columns.find column}
set leftmost-col-index = column-index
}
set record-index = focus-cell.record-index
elseif selection.region-count >= 1 then
let region:RecordGridRegion = {selection.regions.read-one}
set leftmost-col-index = region.first-column
set record-index = region.first-row
set column-index = region.first-column
elseif selection.record-count >= 1 then
set record-index = max-int
{for one-rec-index in selection.records do
{if one-rec-index < record-index then
set record-index = one-rec-index
}
}
set leftmost-col-index = 0
set column-index = 0
elseif selection.column-count >= 1 then
set leftmost-col-index = max-int
{for one-col in selection.columns do
let one-col-index:int = {grid.columns.find one-col}
{if one-col-index >= 0 and
one-col-index < leftmost-col-index
then
set leftmost-col-index = one-col-index
}
}
set record-index = 0
set column-index = leftmost-col-index
}
|| ensure that we have a viable starting cell
{if record-index < 0 or
record-index >= grid.records.size or
column-index < 0 or
column-index >= grid.columns.size
then
{return}
}
|| 4) Loop through a block of cells and locate all target cells
|| This must be done first in case there is a selection, as data
|| updates may cancel the selection.
let constant clip-lines:{Array-of String} =
{clipping.split split-chars = {CharClass.from-any line-delimiter}}
let constant clip-lines-last-index:int = clip-lines.size - 1
let constant target-records:{Array-of int} = {new {Array-of int}}
let constant target-columns:{Array-of int} = {new {Array-of int}}
let constant target-fragments:{Array-of String} = {new {Array-of String}}
{for tag = lines, one-clip-line key line-index in clip-lines do
let cell-fragments:{Array-of String} =
{one-clip-line.split split-chars = cell-splitter}
|| Ensure that blank lines are actually "", not empty;
|| except in the case of the \n$ final "line", which would be a
|| copy artifact and shouldn't become a ghost line in the paste.
{if cell-fragments.empty? and
line-index != clip-lines-last-index
then
{cell-fragments.append ""}
}
{for tag = cells, one-cell-fragment in cell-fragments do
|| 4b) ensure we're within the selection, if any
|| If we had a selection, only paste into selected cells,
|| otherwise skip and discard this text fragment.
{if not selection-empty? then
{if not ({selection.contains-record?
record-index} or
{selection.contains-column?
grid.columns[column-index]} or
{selection.regions-contain-cell?
record-index, column-index}
)
then
{continue tag = cells}
}
}
|| 4c) push the indices for later paste
{target-records.push record-index}
{target-columns.push column-index}
{target-fragments.push one-cell-fragment}
next
|| 4d) move to the next cell
{inc column-index}
{if column-index > (grid.columns.size - 1) then
{continue tag = lines}
}
}
next
|| 4e) move to the next row
{inc record-index}
{if record-index > grid.records.size - 1 then
{break tag = lines}
}
set column-index = leftmost-col-index
}
|| 5) attempt to paste into each targeted cell
{if-non-null rs = grid.record-source then
|| Avoid firing sorts or filters while we are modifying data.
{with rs.batch-events? = true do
{self.perform-paste-new
target-records,
target-columns,
target-fragments
}
}
else
|| While it would be unusual to copy and paste inside an unconnected
|| grid someone might find a use for such a beast.
{self.perform-paste-new
target-records,
target-columns,
target-fragments
}
}
{if-non-null rs = grid.record-source then
set rs.batch-events? = false
}
}
||オープンコントロール perform-past から引用
|| perform-paste-new で、貼り付けを無視する処理を記述に変更
||Ctrl+V で貼り付け処理を行われた際に、 IgnorePasteCellMixin を継承したセルクラスには
||貼り付けを行わないようにする
||※ perform-past だけのオーバーライドでいけるかなと思ったけど、
|| private アクセサなので、execute もオーバーライドして、
|| そこから呼ぶようにしないとだめみたい
|| Perform the actual pasting on a paste operation.
{method private {perform-paste-new
target-records:{Array-of int},
target-columns:{Array-of int},
target-fragments:{Array-of String}
}:void
{if target-records.size != target-columns.size or
target-records.size != target-fragments.size
then
{return}
}
let constant grid:RecordGrid = self.context
let constant ui:RecordGridUI = grid.ui
let target-cell:#RecordGridCell = null
{for i = 0 to target-records.size - 1 do
set target-cell =
{ui.get-cell-at
grid.records[target-records[i]],
grid.columns[target-columns[i]]
}
{type-switch target-cell
case ignore-cell:IgnorePasteCellMixin do
{output {type-of target-cell} & " (IgnorePasteCellMixin)型のセルのため、貼り付けを無視"}
{continue}
}
{if-non-null target-cell then
{if target-cell.enabled? and
target-cell.editable?
then
{try
{target-cell.update-data target-fragments[i]}
catch e:Exception do
|| nothing; continue
}
}
}
}
}
}
||ドロップダウンセル
||貼り付けを無視するセル
{define-class public CustomDropdownCell {inherits StandardDropdownCell ,IgnorePasteCellMixin}
{constructor public {default}
{construct-super.StandardDropdownCell}
}
}
||ドロップダウンセルへの貼り付けを無効化するグリッド
{define-class public CustomRecordGrid {inherits RecordGrid}
{constructor public {default ...}
{construct-super {splice ...}}
}
{method public {create-command name:String}:#Command
{switch name
case "paste" do
||ドロップダウンリストへの貼り付けを抑制
def paste-command = {CustomRecordGridPaste self}
{return paste-command}
else
{return {super.create-command name}}
}
}
}
{def rs =
{RecordSet
{RecordFields
{RecordField "A", domain = String},
{RecordField "dl",
default-value = "",
domain =
{StandardStringDomain
default-value = "",
allowable-values =
{{Array-of String}
"","ABC","DEF","GHI"
}
}},
{RecordField "B", domain = String}
},
{RecordData A = "a", dl = "ABC", B = "b"},
{RecordData },
{RecordData },
{RecordData }
}
}
{def grid =
{CustomRecordGrid
record-source = rs,
{RecordGridColumn "A"},
{RecordGridColumn cell-spec= CustomDropdownCell, "dl"},
{RecordGridColumn "B"}
}
}
{value grid}