| mEditor <- setRefClass("matrixEditor", |
| fields = list( data = "matrix", |
| edits = "list"), |
| methods = list( |
| edit = function(i, j, value) { |
| ## the following string documents the edit method |
| 'Replaces the range [i, j] of the |
| object by value. |
| ' |
| backup <- |
| list(i, j, data[i,j]) |
| data[i,j] <<- value |
| edits <<- c(edits, list(backup)) |
| invisible(value) |
| }, |
| undo = function() { |
| 'Undoes the last edit() operation |
| and update the edits field accordingly. |
| ' |
| prev <- edits |
| if(length(prev)) prev <- prev[[length(prev)]] |
| else stop("No more edits to undo") |
| edit(prev[[1]], prev[[2]], prev[[3]]) |
| ## trim the edits list |
| length(edits) <<- length(edits) - 2 |
| invisible(prev) |
| } |
| )) |
| |
| xMat <- xEdited <- matrix(as.double(1:12),4,3) |
| xEdited[[2,2]] <- 0 |
| xx <- mEditor$new(data = xMat) |
| xx$edit(2, 2, 0) |
| stopifnot(identical(xx$data, xEdited)) |
| xEdited[[1,3]] <- -1 |
| xx$edit(1,3, -1) |
| stopifnot(identical(xx$data, xEdited)) |
| xx$undo() |
| xEdited[[1,3]] <- xMat[[1,3]] |
| stopifnot(identical(xx$data, xEdited)) |
| xx$undo() |
| stopifnot(identical(xx$data, xMat)) |
| |
| ## the tracing method |
| xx$trace(edit, quote(value <- 0)) |
| xx$edit(2,2, -1) # traced should assign 0 |
| stopifnot(identical(xx$data, xEdited)) |
| xx$untrace(edit) |
| xx$edit(1, 3, -1) # now it should use -1 |
| xEdited[[1,3]] <- -1 |
| stopifnot(identical(xx$data, xEdited)) |