Home | History | Annotate | Download | only in sources
      1 /*
      2  * Copyright (C) 2014 Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions are
      6  * met:
      7  *
      8  *     * Redistributions of source code must retain the above copyright
      9  * notice, this list of conditions and the following disclaimer.
     10  *     * Redistributions in binary form must reproduce the above
     11  * copyright notice, this list of conditions and the following disclaimer
     12  * in the documentation and/or other materials provided with the
     13  * distribution.
     14  *     * Neither the name of Google Inc. nor the names of its
     15  * contributors may be used to endorse or promote products derived from
     16  * this software without specific prior written permission.
     17  *
     18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     19  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     21  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     22  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     29  */
     30 
     31 /**
     32  * @constructor
     33  * @param {!WebInspector.SourcesView} sourcesView
     34  * @param {!function():?WebInspector.SourceFrame} currentSourceFrameCallback
     35  */
     36 WebInspector.EditingLocationHistoryManager = function(sourcesView, currentSourceFrameCallback)
     37 {
     38     this._sourcesView = sourcesView;
     39     this._historyManager = new WebInspector.SimpleHistoryManager(WebInspector.EditingLocationHistoryManager.HistoryDepth);
     40     this._currentSourceFrameCallback = currentSourceFrameCallback;
     41 }
     42 
     43 WebInspector.EditingLocationHistoryManager.HistoryDepth = 20;
     44 
     45 WebInspector.EditingLocationHistoryManager.prototype = {
     46     /**
     47      * @param {!WebInspector.UISourceCodeFrame} sourceFrame
     48      */
     49     trackSourceFrameCursorJumps: function(sourceFrame)
     50     {
     51         sourceFrame.addEventListener(WebInspector.SourceFrame.Events.JumpHappened, this._onJumpHappened.bind(this));
     52     },
     53 
     54     /**
     55      * @param {!WebInspector.Event} event
     56      */
     57     _onJumpHappened: function(event)
     58     {
     59         if (event.data.from)
     60             this._updateActiveState(event.data.from);
     61         if (event.data.to)
     62             this._pushActiveState(event.data.to);
     63     },
     64 
     65     rollback: function()
     66     {
     67         this._historyManager.rollback();
     68     },
     69 
     70     rollover: function()
     71     {
     72         this._historyManager.rollover();
     73     },
     74 
     75     updateCurrentState: function()
     76     {
     77         var sourceFrame = this._currentSourceFrameCallback();
     78         if (!sourceFrame)
     79             return;
     80         this._updateActiveState(sourceFrame.textEditor.selection());
     81     },
     82 
     83     pushNewState: function()
     84     {
     85         var sourceFrame = this._currentSourceFrameCallback();
     86         if (!sourceFrame)
     87             return;
     88         this._pushActiveState(sourceFrame.textEditor.selection());
     89     },
     90 
     91     /**
     92      * @param {!WebInspector.TextRange} selection
     93      */
     94     _updateActiveState: function(selection)
     95     {
     96         var active = this._historyManager.active();
     97         if (!active)
     98             return;
     99         var sourceFrame = this._currentSourceFrameCallback();
    100         if (!sourceFrame)
    101             return;
    102         var entry = new WebInspector.EditingLocationHistoryEntry(this._sourcesView, this, sourceFrame, selection);
    103         active.merge(entry);
    104     },
    105 
    106     /**
    107      * @param {!WebInspector.TextRange} selection
    108      */
    109     _pushActiveState: function(selection)
    110     {
    111         var sourceFrame = this._currentSourceFrameCallback();
    112         if (!sourceFrame)
    113             return;
    114         var entry = new WebInspector.EditingLocationHistoryEntry(this._sourcesView, this, sourceFrame, selection);
    115         this._historyManager.push(entry);
    116     },
    117 
    118     /**
    119      * @param {!WebInspector.UISourceCode} uiSourceCode
    120      */
    121     removeHistoryForSourceCode: function(uiSourceCode)
    122     {
    123         function filterOut(entry)
    124         {
    125             return entry._projectId === uiSourceCode.project().id() && entry._path === uiSourceCode.path();
    126         }
    127 
    128         this._historyManager.filterOut(filterOut);
    129     },
    130 }
    131 
    132 
    133 /**
    134  * @constructor
    135  * @implements {WebInspector.HistoryEntry}
    136  * @param {!WebInspector.SourcesView} sourcesView
    137  * @param {!WebInspector.EditingLocationHistoryManager} editingLocationManager
    138  * @param {!WebInspector.SourceFrame} sourceFrame
    139  * @param {!WebInspector.TextRange} selection
    140  */
    141 WebInspector.EditingLocationHistoryEntry = function(sourcesView, editingLocationManager, sourceFrame, selection)
    142 {
    143     this._sourcesView = sourcesView;
    144     this._editingLocationManager = editingLocationManager;
    145     var uiSourceCode = sourceFrame.uiSourceCode();
    146     this._projectId = uiSourceCode.project().id();
    147     this._path = uiSourceCode.path();
    148 
    149     var position = this._positionFromSelection(selection);
    150     this._positionHandle = sourceFrame.textEditor.textEditorPositionHandle(position.lineNumber, position.columnNumber);
    151 }
    152 
    153 WebInspector.EditingLocationHistoryEntry.prototype = {
    154     /**
    155      * @param {!WebInspector.HistoryEntry} entry
    156      */
    157     merge: function(entry)
    158     {
    159         if (this._projectId !== entry._projectId || this._path !== entry._path)
    160             return;
    161         this._positionHandle = entry._positionHandle;
    162     },
    163 
    164     /**
    165      * @param {!WebInspector.TextRange} selection
    166      * @return {!{lineNumber: number, columnNumber: number}}
    167      */
    168     _positionFromSelection: function(selection)
    169     {
    170         return {
    171             lineNumber: selection.endLine,
    172             columnNumber: selection.endColumn
    173         };
    174     },
    175 
    176     /**
    177      * @return {boolean}
    178      */
    179     valid: function()
    180     {
    181         var position = this._positionHandle.resolve();
    182         var uiSourceCode = WebInspector.workspace.project(this._projectId).uiSourceCode(this._path);
    183         return !!(position && uiSourceCode);
    184     },
    185 
    186     reveal: function()
    187     {
    188         var position = this._positionHandle.resolve();
    189         var uiSourceCode = WebInspector.workspace.project(this._projectId).uiSourceCode(this._path);
    190         if (!position || !uiSourceCode)
    191             return;
    192 
    193         this._editingLocationManager.updateCurrentState();
    194         this._sourcesView.showSourceLocation(uiSourceCode, position.lineNumber, position.columnNumber);
    195     }
    196 };
    197