browser/devtools/shared/undo.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* -*- Mode: Javascript; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     2 /* vim: set ft=javascript ts=2 et sw=2 tw=80: */
     3 /* This Source Code Form is subject to the terms of the Mozilla Public
     4  * License, v. 2.0. If a copy of the MPL was not distributed with this
     5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     7 /**
     8  * A simple undo stack manager.
     9  *
    10  * Actions are added along with the necessary code to
    11  * reverse the action.
    12  *
    13  * @param function aChange Called whenever the size or position
    14  *   of the undo stack changes, to use for updating undo-related
    15  *   UI.
    16  * @param integer aMaxUndo Maximum number of undo steps.
    17  *   defaults to 50.
    18  */
    19 function UndoStack(aMaxUndo)
    20 {
    21   this.maxUndo = aMaxUndo || 50;
    22   this._stack = [];
    23 }
    25 exports.UndoStack = UndoStack;
    27 UndoStack.prototype = {
    28   // Current index into the undo stack.  Is positioned after the last
    29   // currently-applied change.
    30   _index: 0,
    32   // The current batch depth (see startBatch() for details)
    33   _batchDepth: 0,
    35   destroy: function Undo_destroy()
    36   {
    37     this.uninstallController();
    38     delete this._stack;
    39   },
    41   /**
    42    * Start a collection of related changes.  Changes will be batched
    43    * together into one undo/redo item until endBatch() is called.
    44    *
    45    * Batches can be nested, in which case the outer batch will contain
    46    * all items from the inner batches.  This allows larger user
    47    * actions made up of a collection of smaller actions to be
    48    * undone as a single action.
    49    */
    50   startBatch: function Undo_startBatch()
    51   {
    52     if (this._batchDepth++ === 0) {
    53       this._batch = [];
    54     }
    55   },
    57   /**
    58    * End a batch of related changes, performing its action and adding
    59    * it to the undo stack.
    60    */
    61   endBatch: function Undo_endBatch()
    62   {
    63     if (--this._batchDepth > 0) {
    64       return;
    65     }
    67     // Cut off the end of the undo stack at the current index,
    68     // and the beginning to prevent a stack larger than maxUndo.
    69     let start = Math.max((this._index + 1) - this.maxUndo, 0);
    70     this._stack = this._stack.slice(start, this._index);
    72     let batch = this._batch;
    73     delete this._batch;
    74     let entry = {
    75       do: function() {
    76         for (let item of batch) {
    77           item.do();
    78         }
    79       },
    80       undo: function() {
    81         for (let i = batch.length - 1; i >= 0; i--) {
    82           batch[i].undo();
    83         }
    84       }
    85     };
    86     this._stack.push(entry);
    87     this._index = this._stack.length;
    88     entry.do();
    89     this._change();
    90   },
    92   /**
    93    * Perform an action, adding it to the undo stack.
    94    *
    95    * @param function aDo Called to perform the action.
    96    * @param function aUndo Called to reverse the action.
    97    */
    98   do: function Undo_do(aDo, aUndo) {
    99     this.startBatch();
   100     this._batch.push({ do: aDo, undo: aUndo });
   101     this.endBatch();
   102   },
   104   /*
   105    * Returns true if undo() will do anything.
   106    */
   107   canUndo: function Undo_canUndo()
   108   {
   109     return this._index > 0;
   110   },
   112   /**
   113    * Undo the top of the undo stack.
   114    *
   115    * @return true if an action was undone.
   116    */
   117   undo: function Undo_canUndo()
   118   {
   119     if (!this.canUndo()) {
   120       return false;
   121     }
   122     this._stack[--this._index].undo();
   123     this._change();
   124     return true;
   125   },
   127   /**
   128    * Returns true if redo() will do anything.
   129    */
   130   canRedo: function Undo_canRedo()
   131   {
   132     return this._stack.length > this._index;
   133   },
   135   /**
   136    * Redo the most recently undone action.
   137    *
   138    * @return true if an action was redone.
   139    */
   140   redo: function Undo_canRedo()
   141   {
   142     if (!this.canRedo()) {
   143       return false;
   144     }
   145     this._stack[this._index++].do();
   146     this._change();
   147     return true;
   148   },
   150   _change: function Undo__change()
   151   {
   152     if (this._controllerWindow) {
   153       this._controllerWindow.goUpdateCommand("cmd_undo");
   154       this._controllerWindow.goUpdateCommand("cmd_redo");
   155     }
   156   },
   158   /**
   159    * ViewController implementation for undo/redo.
   160    */
   162   /**
   163    * Install this object as a command controller.
   164    */
   165   installController: function Undo_installController(aControllerWindow)
   166   {
   167     this._controllerWindow = aControllerWindow;
   168     aControllerWindow.controllers.appendController(this);
   169   },
   171   /**
   172    * Uninstall this object from the command controller.
   173    */
   174   uninstallController: function Undo_uninstallController()
   175   {
   176     if (!this._controllerWindow) {
   177       return;
   178     }
   179     this._controllerWindow.controllers.removeController(this);
   180   },
   182   supportsCommand: function Undo_supportsCommand(aCommand)
   183   {
   184     return (aCommand == "cmd_undo" ||
   185             aCommand == "cmd_redo");
   186   },
   188   isCommandEnabled: function Undo_isCommandEnabled(aCommand)
   189   {
   190     switch(aCommand) {
   191       case "cmd_undo": return this.canUndo();
   192       case "cmd_redo": return this.canRedo();
   193     };
   194     return false;
   195   },
   197   doCommand: function Undo_doCommand(aCommand)
   198   {
   199     switch(aCommand) {
   200       case "cmd_undo": return this.undo();
   201       case "cmd_redo": return this.redo();
   202     }
   203   },
   205   onEvent: function Undo_onEvent(aEvent) {},
   206 }

mercurial