| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 | |
| 5 /** | |
| 6 * The base class for commands that may be placed on the undo/redo stack. | |
| 7 */ | |
| 8 class Command { | |
| 9 | |
| 10 String _description; | |
| 11 Spreadsheet _spreadsheet; | |
| 12 | |
| 13 String get description() => _description; | |
| 14 | |
| 15 /** | |
| 16 * Constructs a new command on a given spreadsheet. | |
| 17 * | |
| 18 * The description is currently used for logging during undo/redo events. | |
| 19 */ | |
| 20 Command(this._spreadsheet, this._description) { } | |
| 21 | |
| 22 /** | |
| 23 * Perform the action associated with this command. | |
| 24 */ | |
| 25 void execute() { | |
| 26 throw new NotImplementedException(); | |
| 27 } | |
| 28 | |
| 29 String toString() => "Command[${_description}]"; | |
| 30 | |
| 31 /** | |
| 32 * Undo the action. | |
| 33 * | |
| 34 * This method should reverse any operation done during [execute()]. | |
| 35 */ | |
| 36 void unexecute() { | |
| 37 throw new NotImplementedException(); | |
| 38 } | |
| 39 } | |
| 40 | |
| 41 /** | |
| 42 * The command for inserting a block of cells and shifting down. | |
| 43 */ | |
| 44 class InsertBlockAndShiftDownCommand extends Command { | |
| 45 | |
| 46 RowCol _maxCorner; | |
| 47 RowCol _minCorner; | |
| 48 | |
| 49 /** | |
| 50 * Create a new command. | |
| 51 * | |
| 52 * [minCorner] is the top left corner of the block to insert, while [maxCorner
] is the | |
| 53 * bottom right corner. The shifted block includes both corners. | |
| 54 */ | |
| 55 InsertBlockAndShiftDownCommand(Spreadsheet spreadsheet, this._minCorner, this.
_maxCorner) | |
| 56 : super(spreadsheet, "Insert/Shift Down") { } | |
| 57 | |
| 58 void execute() { | |
| 59 _spreadsheet.insertBlockAndShiftDown(_minCorner, _maxCorner); | |
| 60 } | |
| 61 | |
| 62 void unexecute() { | |
| 63 _spreadsheet.removeBlockAndShiftUp(_minCorner, _maxCorner); | |
| 64 } | |
| 65 } | |
| 66 | |
| 67 /** | |
| 68 * The command for inserting a block of cells and shifting right. | |
| 69 */ | |
| 70 class InsertBlockAndShiftRightCommand extends Command { | |
| 71 | |
| 72 RowCol _maxCorner; | |
| 73 RowCol _minCorner; | |
| 74 | |
| 75 /** | |
| 76 * Create a new command. | |
| 77 * | |
| 78 * [minCorner] is the top left corner of the block to insert, while [maxCorner
] is the | |
| 79 * bottom right corner. The shifted block includes both corners. | |
| 80 */ | |
| 81 InsertBlockAndShiftRightCommand(Spreadsheet spreadsheet, this._minCorner, this
._maxCorner) | |
| 82 : super(spreadsheet, "Insert/Shift Right") { } | |
| 83 | |
| 84 void execute() { | |
| 85 _spreadsheet.insertBlockAndShiftRight(_minCorner, _maxCorner); | |
| 86 } | |
| 87 | |
| 88 void unexecute() { | |
| 89 _spreadsheet.removeBlockAndShiftLeft(_minCorner, _maxCorner); | |
| 90 } | |
| 91 } | |
| 92 | |
| 93 /** | |
| 94 * The command for inserting columns into the spreadsheet. | |
| 95 */ | |
| 96 class InsertColumnsCommand extends Command { | |
| 97 | |
| 98 int _maxColumn; | |
| 99 int _minColumn; | |
| 100 | |
| 101 /** | |
| 102 * Create a new command. | |
| 103 * | |
| 104 * [minColumn] is the leftmost column of the block to insert, while [maxColumn
] is the rightmost | |
| 105 * column to be inserted. | |
| 106 */ | |
| 107 InsertColumnsCommand(Spreadsheet spreadsheet, this._minColumn, this._maxColumn
) | |
| 108 : super(spreadsheet, "Insert Columns") { } | |
| 109 | |
| 110 void execute() { | |
| 111 _spreadsheet.insertColumns(_minColumn, _maxColumn); | |
| 112 } | |
| 113 | |
| 114 void unexecute() { | |
| 115 _spreadsheet.removeColumns(_minColumn, _maxColumn); | |
| 116 } | |
| 117 } | |
| 118 | |
| 119 /** | |
| 120 * The command for inserting rows into the spreadsheet. | |
| 121 */ | |
| 122 class InsertRowsCommand extends Command { | |
| 123 | |
| 124 int _maxRow; | |
| 125 int _minRow; | |
| 126 | |
| 127 /** | |
| 128 * Create a new command. | |
| 129 * | |
| 130 * [minRow] is the topmost row of the block to insert, while [maxRow] is the b
ottommost | |
| 131 * row to be inserted. | |
| 132 */ | |
| 133 InsertRowsCommand(Spreadsheet spreadsheet, this._minRow, this._maxRow) | |
| 134 : super(spreadsheet, "Insert Rows") { } | |
| 135 | |
| 136 void execute() { | |
| 137 _spreadsheet.insertRows(_minRow, _maxRow); | |
| 138 } | |
| 139 | |
| 140 void unexecute() { | |
| 141 _spreadsheet.removeRows(_minRow, _maxRow); | |
| 142 } | |
| 143 } | |
| 144 | |
| 145 /** | |
| 146 * The command to reset the row and column sizes. | |
| 147 */ | |
| 148 class ResetRowColumnSizesCommand extends Command { | |
| 149 | |
| 150 List<List<int>> _rowColumnSizes; | |
| 151 | |
| 152 ResetRowColumnSizesCommand(Spreadsheet spreadsheet) | |
| 153 : super(spreadsheet, "Reset Row/Column Sizes") { | |
| 154 _rowColumnSizes = _spreadsheet.layout.getRowColumnSizes(); | |
| 155 } | |
| 156 | |
| 157 void execute() { | |
| 158 _spreadsheet.layout.resetSizes(); | |
| 159 } | |
| 160 | |
| 161 void unexecute() { | |
| 162 _spreadsheet.layout.setRowColumnSizes(_rowColumnSizes); | |
| 163 } | |
| 164 } | |
| 165 | |
| 166 /** | |
| 167 * The command to resize a row or column. | |
| 168 */ | |
| 169 class ResizeRowColumnCommand extends Command { | |
| 170 | |
| 171 int _index; | |
| 172 int _oldSize; | |
| 173 int _rowOrCol; | |
| 174 int _size; | |
| 175 | |
| 176 /** | |
| 177 * Create a new command. | |
| 178 * | |
| 179 * rowOrCol indicates which of a row or column we are resizing. Index indicate
s which | |
| 180 * row or column. Size is the new size and oldSize is the former size. | |
| 181 */ | |
| 182 ResizeRowColumnCommand(Spreadsheet spreadsheet, this._rowOrCol, this._index, t
his._size, | |
| 183 this._oldSize) : super(spreadsheet, "Resize Row/Column") { } | |
| 184 | |
| 185 void execute() { | |
| 186 if (_rowOrCol == Spreadsheet.COL) { | |
| 187 _spreadsheet.setColumnWidth(_index, _size); | |
| 188 } else { | |
| 189 _spreadsheet.setRowHeight(_index, _size); | |
| 190 } | |
| 191 } | |
| 192 | |
| 193 void unexecute() { | |
| 194 if (_rowOrCol == Spreadsheet.COL) { | |
| 195 _spreadsheet.setColumnWidth(_index, _oldSize); | |
| 196 } else { | |
| 197 _spreadsheet.setRowHeight(_index, _oldSize); | |
| 198 } | |
| 199 } | |
| 200 } | |
| 201 | |
| 202 /** | |
| 203 * A command to set the content of a single cell, in string form. | |
| 204 */ | |
| 205 class SetCellContentsCommand extends Command { | |
| 206 | |
| 207 String _content; | |
| 208 String _oldContent; | |
| 209 RowCol _rowCol; | |
| 210 Style _style; | |
| 211 | |
| 212 /** | |
| 213 * Create a new command, given the new content for the cell. | |
| 214 */ | |
| 215 SetCellContentsCommand(CellLocation location, this._content) | |
| 216 : super(location.spreadsheet, "Set Cell Content") { | |
| 217 _rowCol = location.rowCol; | |
| 218 Cell oldCell = location.getCell(); | |
| 219 if (oldCell == null) { | |
| 220 _oldContent = null; | |
| 221 } else { | |
| 222 _oldContent = oldCell.getContentString(); | |
| 223 } | |
| 224 } | |
| 225 | |
| 226 void execute() { | |
| 227 _spreadsheet.setCellFromContentString(_rowCol, _content); | |
| 228 _spreadsheet.markDirty(_rowCol); | |
| 229 } | |
| 230 | |
| 231 void unexecute() { | |
| 232 String rowColString = _rowCol.toString(); | |
| 233 if (_oldContent == null) { | |
| 234 _spreadsheet.setCellContent(_rowCol, null); | |
| 235 } else { | |
| 236 _spreadsheet.setCellFromContentString(_rowCol, _oldContent); | |
| 237 } | |
| 238 _spreadsheet.markDirty(_rowCol); | |
| 239 } | |
| 240 } | |
| 241 | |
| 242 /** | |
| 243 * A type for the action method used to set style properties. | |
| 244 */ | |
| 245 typedef Style SetStyleFunction(Style s, int index); | |
| 246 | |
| 247 /** | |
| 248 * A command to set the style of a range of cells. | |
| 249 */ | |
| 250 class SetStyleCommand extends Command { | |
| 251 | |
| 252 SetStyleFunction _action; | |
| 253 CellRange _cellRange; | |
| 254 int _index; | |
| 255 List<UndoableAction> _oldCellStyles; | |
| 256 | |
| 257 /** | |
| 258 * Create a new command. | |
| 259 * | |
| 260 * [cellRange] is the range of cells to apply the style change to. [index] is
passed to the | |
| 261 * action function, allowing a single action to be used for multiple propertie
s. [action] is | |
| 262 * the function to apply to the range. | |
| 263 */ | |
| 264 SetStyleCommand(CellRange cellRange, this._index, this._action) : super(cellRa
nge.spreadsheet, | |
| 265 "Set Style") { | |
| 266 _cellRange = cellRange; | |
| 267 } | |
| 268 | |
| 269 void execute() { | |
| 270 _spreadsheet.clearDirtyCells(); | |
| 271 _oldCellStyles = new List<UndoableAction>(); | |
| 272 _spreadsheet.trackDeltas(_oldCellStyles); | |
| 273 | |
| 274 bool isSheet = _cellRange.isSheetSelection(); | |
| 275 bool isCol = _cellRange.isColumnSelection(); | |
| 276 bool isRow = _cellRange.isRowSelection(); | |
| 277 RowColStyle s; | |
| 278 if (isSheet) { | |
| 279 s = _spreadsheet.getSheetStyle(); | |
| 280 _spreadsheet.setSheetStyle(_updateStyle(s)); | |
| 281 } else if (isRow) { | |
| 282 for (int row = _cellRange.minCorner.row; row <= _cellRange.maxCorner.row;
row++) { | |
| 283 s = _spreadsheet.getRowStyle(row); | |
| 284 _spreadsheet.setRowStyle(row, _updateStyle(s)); | |
| 285 } | |
| 286 } else if (isCol) { | |
| 287 for (int col = _cellRange.minCorner.col; col <= _cellRange.maxCorner.col;
col++) { | |
| 288 s = _spreadsheet.getColumnStyle(col); | |
| 289 _spreadsheet.setColumnStyle(col, _updateStyle(s)); | |
| 290 } | |
| 291 } | |
| 292 | |
| 293 // Perform the action the intersection between the range and the active area | |
| 294 CellRange range = _cellRange.makeBounded(); | |
| 295 _cellRange.forEach((CellLocation location) { | |
| 296 Cell c = location.getCell(); | |
| 297 // Don't force cell creation for whole row/col selection | |
| 298 if (c == null && !isCol && !isRow) { | |
| 299 Style newStyle = _action(new Style(), _index); | |
| 300 location.spreadsheet.setCellStyle(location.rowCol, newStyle); | |
| 301 } | |
| 302 if (c != null) { | |
| 303 Style newStyle = _action(c.style, _index); | |
| 304 location.spreadsheet.setCellStyle(location.rowCol, newStyle); | |
| 305 } | |
| 306 }); | |
| 307 } | |
| 308 | |
| 309 void unexecute() { | |
| 310 _spreadsheet.clearDirtyCells(); | |
| 311 int count = _oldCellStyles.length; | |
| 312 for (int i = count - 1; i >= 0; --i) { | |
| 313 _oldCellStyles[i].undoAction(_spreadsheet); | |
| 314 }; | |
| 315 _oldCellStyles = null; | |
| 316 } | |
| 317 | |
| 318 // Return a RowColStyle that is the result of performing the style setting act
ion on | |
| 319 // an existing RowColStyle. | |
| 320 RowColStyle _updateStyle(RowColStyle s) { | |
| 321 Style oldStyle = s == null ? new Style() : s.style; | |
| 322 // Perform the style setting action | |
| 323 Style newStyle = _action(oldStyle, _index); | |
| 324 RowColStyle newRCStyle = new RowColStyle(newStyle); | |
| 325 return newRCStyle; | |
| 326 } | |
| 327 } | |
| OLD | NEW |