Curl Global Community
特定のセルに対するペーストを無効にしたい - Printable Version

+- Curl Global Community (http://communities.curl.com)
+-- Forum: Discussions (http://communities.curl.com/forumdisplay.php?fid=1)
+--- Forum: General Curl questions (http://communities.curl.com/forumdisplay.php?fid=2)
+--- Thread: 特定のセルに対するペーストを無効にしたい (/showthread.php?tid=1049)



特定のセルに対するペーストを無効にしたい - umemura - 03-11-2014

グリッド(RecordGrid)に対してCtrl+V 等で、データが貼り付けられた際に、
特定のセルだけ、貼付けを無効にするには、どんな方法がありますか?




RE: 特定のセルに対するペーストを無効にしたい - umemura - 03-11-2014


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}