Title: [128281] trunk/Source/WebCore
Revision
128281
Author
[email protected]
Date
2012-09-12 02:32:39 -0700 (Wed, 12 Sep 2012)

Log Message

Web Inspector: Implement search and filtering on Timeline panel
https://bugs.webkit.org/show_bug.cgi?id=95445

Patch by Eugene Klyuchnikov <[email protected]> on 2012-09-12
Reviewed by Yury Semikhatsky.

Implemented textual search/filtering on Timeline panel.
Fixed "revealRecordAt" - now it scans all records in window,
now only visible ones.

* inspector/front-end/TimelineOverviewPane.js:
(WebInspector.TimelineWindowFilter):
Extracted from TimelineOverviewPane class.
* inspector/front-end/TimelinePanel.js:
(WebInspector.TimelinePanel):
(WebInspector.TimelinePanel.prototype.revealRecordAt):
Used DFS to scan records.
(WebInspector.TimelinePanel.prototype._revealRecord):
Extracted common code.
(WebInspector.TimelineSearchFilter):
Implemented search and filtration.

Modified Paths

Diff

Modified: trunk/Source/WebCore/ChangeLog (128280 => 128281)


--- trunk/Source/WebCore/ChangeLog	2012-09-12 09:17:25 UTC (rev 128280)
+++ trunk/Source/WebCore/ChangeLog	2012-09-12 09:32:39 UTC (rev 128281)
@@ -1,3 +1,26 @@
+2012-09-12  Eugene Klyuchnikov  <[email protected]>
+
+        Web Inspector: Implement search and filtering on Timeline panel
+        https://bugs.webkit.org/show_bug.cgi?id=95445
+
+        Reviewed by Yury Semikhatsky.
+
+        Implemented textual search/filtering on Timeline panel.
+        Fixed "revealRecordAt" - now it scans all records in window,
+        now only visible ones.
+
+        * inspector/front-end/TimelineOverviewPane.js:
+        (WebInspector.TimelineWindowFilter):
+        Extracted from TimelineOverviewPane class.
+        * inspector/front-end/TimelinePanel.js:
+        (WebInspector.TimelinePanel):
+        (WebInspector.TimelinePanel.prototype.revealRecordAt):
+        Used DFS to scan records.
+        (WebInspector.TimelinePanel.prototype._revealRecord):
+        Extracted common code.
+        (WebInspector.TimelineSearchFilter):
+        Implemented search and filtration.
+
 2012-09-12  Ilya Tikhonovsky  <[email protected]>
 
         Web Inspector: NMI move String* instrumentation to wtf.

Modified: trunk/Source/WebCore/inspector/front-end/TimelineOverviewPane.js (128280 => 128281)


--- trunk/Source/WebCore/inspector/front-end/TimelineOverviewPane.js	2012-09-12 09:17:25 UTC (rev 128280)
+++ trunk/Source/WebCore/inspector/front-end/TimelineOverviewPane.js	2012-09-12 09:32:39 UTC (rev 128281)
@@ -31,7 +31,6 @@
 /**
  * @constructor
  * @extends {WebInspector.View}
- * @implements {WebInspector.TimelinePresentationModel.Filter}
  * @param {WebInspector.TimelineModel} model
  */
 WebInspector.TimelineOverviewPane = function(model)
@@ -274,14 +273,6 @@
         this._update();
     },
 
-    /**
-     * @param {WebInspector.TimelinePresentationModel.Record} record
-     */
-    accept: function(record)
-    {
-        return record.lastChildEndTime >= this._windowStartTime && record.startTime <= this._windowEndTime;
-    },
-
     windowStartTime: function()
     {
         return this._windowStartTime || this._model.minimumRecordTime();
@@ -1232,3 +1223,24 @@
 }
 
 WebInspector.TimelineFrameOverview.prototype.__proto__ = WebInspector.View.prototype;
+
+/**
+ * @param {WebInspector.TimelineOverviewPane} pane
+ * @constructor
+ * @implements {WebInspector.TimelinePresentationModel.Filter}
+ */
+WebInspector.TimelineWindowFilter = function(pane)
+{
+    this._pane = pane;
+}
+
+WebInspector.TimelineWindowFilter.prototype = {
+    /**
+     * @param {!WebInspector.TimelinePresentationModel.Record} record
+     * @return {boolean}
+     */
+    accept: function(record)
+    {
+        return record.lastChildEndTime >= this._pane._windowStartTime && record.startTime <= this._pane._windowEndTime;
+    }
+}

Modified: trunk/Source/WebCore/inspector/front-end/TimelinePanel.js (128280 => 128281)


--- trunk/Source/WebCore/inspector/front-end/TimelinePanel.js	2012-09-12 09:17:25 UTC (rev 128280)
+++ trunk/Source/WebCore/inspector/front-end/TimelinePanel.js	2012-09-12 09:32:39 UTC (rev 128281)
@@ -145,9 +145,9 @@
 
     this._allRecordsCount = 0;
 
-    this._presentationModel.addFilter(this._overviewPane);
+    this._presentationModel.addFilter(new WebInspector.TimelineWindowFilter(this._overviewPane));
     this._presentationModel.addFilter(new WebInspector.TimelineCategoryFilter()); 
-    this._presentationModel.addFilter(new WebInspector.TimelineIsLongFilter(this)); 
+    this._presentationModel.addFilter(new WebInspector.TimelineIsLongFilter(this));
 }
 
 // Define row height, should be in sync with styles for timeline graphs.
@@ -671,6 +671,7 @@
     _invalidateAndScheduleRefresh: function(preserveBoundaries)
     {
         this._presentationModel.invalidateFilteredRecords();
+        delete this._searchResults;
         this._scheduleRefresh(preserveBoundaries);
     },
 
@@ -724,18 +725,19 @@
 
     revealRecordAt: function(time)
     {
-        var recordsInWindow = this._presentationModel.filteredRecords();
         var recordToReveal;
-        for (var i = 0; i < recordsInWindow.length; ++i) {
-            var record = recordsInWindow[i];
+        function findRecordToReveal(record)
+        {
             if (record.containsTime(time)) {
                 recordToReveal = record;
-                break;
+                return true;
             }
             // If there is no record containing the time than use the latest one before that time.
             if (!recordToReveal || record.endTime < time && recordToReveal.endTime < record.endTime)
                 recordToReveal = record;
+            return false;
         }
+        WebInspector.TimelinePresentationModel.forAllRecords(this._presentationModel.rootRecord().children, null, findRecordToReveal);
 
         // The record ends before the window left bound so scroll to the top.
         if (!recordToReveal) {
@@ -743,9 +745,21 @@
             return;
         }
 
+        this._revealRecord(recordToReveal);
+    },
+
+    _revealRecord: function(recordToReveal)
+    {
         // Expand all ancestors.
-        for (var parent = recordToReveal.parent; parent !== this._rootRecord(); parent = parent.parent)
+        var treeUpdated = false;
+        for (var parent = recordToReveal.parent; parent !== this._rootRecord(); parent = parent.parent) {
+            treeUpdated = treeUpdated || parent.collapsed;
             parent.collapsed = false;
+        }
+        if (treeUpdated)
+            this._invalidateAndScheduleRefresh(true);
+
+        var recordsInWindow = this._presentationModel.filteredRecords();
         var index = recordsInWindow.indexOf(recordToReveal);
         this._containerElement.scrollTop = index * WebInspector.TimelinePanel.rowHeight;
     },
@@ -832,6 +846,7 @@
         this._itemsGraphsElement.insertBefore(this._graphRowsElement, this._bottomGapElement);
         this._itemsGraphsElement.appendChild(this._expandElements);
         this._adjustScrollPosition((recordsInWindow.length + this._headerLineCount) * rowHeight);
+        this._updateSearchHighlight(false);
 
         return recordsInWindow.length;
     },
@@ -1002,6 +1017,142 @@
 
         style.textContent = Object.values(categories).map(WebInspector.TimelinePresentationModel.createStyleRuleForCategory).join("\n");
         document.head.appendChild(style);
+    },
+
+    jumpToNextSearchResult: function()
+    {
+        this._jumpToAdjacentRecord(1);
+    },
+
+    jumpToPreviousSearchResult: function()
+    {
+        this._jumpToAdjacentRecord(-1);
+    },
+
+    _jumpToAdjacentRecord: function(offset)
+    {
+        if (!this._searchResults || !this._searchResults.length || !this._selectedSearchResult)
+            return;
+        var index = this._searchResults.indexOf(this._selectedSearchResult);
+        index = (index + offset + this._searchResults.length) % this._searchResults.length;
+        this._selectSearchResult(index);
+        this._highlightSelectedSearchResult(true);
+    },
+
+    _selectSearchResult: function(index)
+    {
+        this._selectedSearchResult = this._searchResults[index];
+        WebInspector.searchController.updateCurrentMatchIndex(index, this);
+    },
+
+    _highlightSelectedSearchResult: function(revealRecord)
+    {
+        this._clearHighlight();
+        if (this._searchFilter)
+            return;
+
+        var record = this._selectedSearchResult;
+        if (!record)
+            return;
+
+        for (var element = this._sidebarListElement.firstChild; element; element = element.nextSibling) {
+            if (element.row._record === record) {
+                element.row.highlight(this._searchRegExp, this._highlightDomChanges);
+                return;
+            }
+        }
+
+        if (revealRecord)
+            this._revealRecord(record);
+    },
+
+    _clearHighlight: function()
+    {
+        if (this._highlightDomChanges)
+            WebInspector.revertDomChanges(this._highlightDomChanges);
+        this._highlightDomChanges = [];
+    },
+
+    /**
+     * @param {boolean} revealRecord
+     */
+    _updateSearchHighlight: function(revealRecord)
+    {
+        if (this._searchFilter || !this._searchRegExp) {
+            this._clearHighlight();
+            return;
+        }
+
+        if (!this._searchResults)
+            this._updateSearchResults();
+
+        this._highlightSelectedSearchResult(revealRecord);
+    },
+
+    _updateSearchResults: function() {
+        var searchRegExp = this._searchRegExp;
+        if (!searchRegExp)
+            return;
+
+        var matches = [];
+        var presentationModel = this._presentationModel;
+
+        function processRecord(record)
+        {
+            if (presentationModel.isVisible(record) && WebInspector.TimelineRecordListRow.testContentMatching(record, searchRegExp))
+                matches.push(record);
+            return false;
+        }
+        WebInspector.TimelinePresentationModel.forAllRecords(presentationModel.rootRecord().children, processRecord);
+
+        var matchesCount = matches.length;
+        if (matchesCount) {
+            this._searchResults = matches;
+            WebInspector.searchController.updateSearchMatchesCount(matchesCount, this);
+
+            var selectedIndex = matches.indexOf(this._selectedSearchResult);
+            if (selectedIndex === -1)
+                selectedIndex = 0;
+            this._selectSearchResult(selectedIndex);
+        } else {
+            WebInspector.searchController.updateSearchMatchesCount(0, this);
+            delete this._selectedSearchResult;
+        }
+    },
+
+    searchCanceled: function()
+    {
+        this._clearHighlight();
+        delete this._searchResults;
+        delete this._selectedSearchResult;
+        delete this._searchRegExp;
+    },
+
+    /**
+     * @return {boolean}
+     */
+    canFilter: function()
+    {
+        return true;
+    },
+
+    performFilter: function(searchQuery)
+    {
+        this._presentationModel.removeFilter(this._searchFilter);
+        delete this._searchFilter;
+        this.searchCanceled();
+        if (searchQuery) {
+            this._searchFilter = new WebInspector.TimelineSearchFilter(createPlainTextSearchRegex(searchQuery, "i"));
+            this._presentationModel.addFilter(this._searchFilter);
+        }
+        this._invalidateAndScheduleRefresh(true);
+    },
+
+    performSearch: function(searchQuery)
+    {
+        this._searchRegExp = createPlainTextSearchRegex(searchQuery, "i");
+        delete this._searchResults;
+        this._updateSearchHighlight(true);
     }
 }
 
@@ -1151,6 +1302,13 @@
         }
     },
 
+    highlight: function(regExp, domChanges)
+    {
+        var matchInfo = this.element.textContent.match(regExp);
+        if (matchInfo)
+            WebInspector.highlightSearchResult(this.element, matchInfo.index, matchInfo[0].length, domChanges);
+    },
+
     dispose: function()
     {
         this.element.parentElement.removeChild(this.element);
@@ -1158,6 +1316,15 @@
 }
 
 /**
+ * @param {!WebInspector.TimelinePresentationModel.Record} record
+ * @param {!RegExp} regExp
+ */
+WebInspector.TimelineRecordListRow.testContentMatching = function(record, regExp)
+{
+    return regExp.test(record.title + " (" + record.details() + ")");
+}
+
+/**
  * @constructor
  */
 WebInspector.TimelineRecordGraphRow = function(graphContainer, scheduleRefresh)
@@ -1271,7 +1438,8 @@
 
 WebInspector.TimelineCategoryFilter.prototype = {
     /**
-     * @param {WebInspector.TimelinePresentationModel.Record} record
+     * @param {!WebInspector.TimelinePresentationModel.Record} record
+     * @return {boolean}
      */
     accept: function(record)
     {
@@ -1291,10 +1459,33 @@
 
 WebInspector.TimelineIsLongFilter.prototype = {
     /**
-     * @param {WebInspector.TimelinePresentationModel.Record} record
+     * @param {!WebInspector.TimelinePresentationModel.Record} record
+     * @return {boolean}
      */
     accept: function(record)
     {
         return this._panel._showShortEvents || record.isLong();
     }
 }
+
+/**
+ * @param {!RegExp} regExp
+ * @constructor
+ * @implements {WebInspector.TimelinePresentationModel.Filter}
+ */
+WebInspector.TimelineSearchFilter = function(regExp)
+{
+    this._regExp = regExp;
+}
+
+WebInspector.TimelineSearchFilter.prototype = {
+
+    /**
+     * @param {!WebInspector.TimelinePresentationModel.Record} record
+     * @return {boolean}
+     */
+    accept: function(record)
+    {
+        return WebInspector.TimelineRecordListRow.testContentMatching(record, this._regExp);
+    }
+}

Modified: trunk/Source/WebCore/inspector/front-end/TimelinePresentationModel.js (128280 => 128281)


--- trunk/Source/WebCore/inspector/front-end/TimelinePresentationModel.js	2012-09-12 09:17:25 UTC (rev 128280)
+++ trunk/Source/WebCore/inspector/front-end/TimelinePresentationModel.js	2012-09-12 09:32:39 UTC (rev 128281)
@@ -226,13 +226,23 @@
 
 WebInspector.TimelinePresentationModel.prototype = {
     /**
-     * @param {WebInspector.TimelinePresentationModel.Filter} filter
+     * @param {!WebInspector.TimelinePresentationModel.Filter} filter
      */
     addFilter: function(filter)
     {
         this._filters.push(filter);
     },
 
+    /**
+     * @param {!WebInspector.TimelinePresentationModel.Filter} filter
+     */
+    removeFilter: function(filter)
+    {
+        var index = this._filters.indexOf(filter);
+        if (index !== -1)
+            this._filters.splice(index, 1);
+    },
+
     rootRecord: function()
     {
         return this._rootRecord;
@@ -1112,7 +1122,8 @@
 
 WebInspector.TimelinePresentationModel.Filter.prototype = {
     /**
-     * @param {WebInspector.TimelinePresentationModel.Record} record
+     * @param {!WebInspector.TimelinePresentationModel.Record} record
+     * @return {boolean}
      */
     accept: function(record) { return false; }
 }

Modified: trunk/Source/WebCore/inspector/front-end/utilities.js (128280 => 128281)


--- trunk/Source/WebCore/inspector/front-end/utilities.js	2012-09-12 09:17:25 UTC (rev 128280)
+++ trunk/Source/WebCore/inspector/front-end/utilities.js	2012-09-12 09:32:39 UTC (rev 128281)
@@ -631,7 +631,7 @@
 /**
  * @param {string} query
  * @param {string=} flags
- * @return {RegExp}
+ * @return {!RegExp}
  */
 function createPlainTextSearchRegex(query, flags)
 {
_______________________________________________
webkit-changes mailing list
[email protected]
http://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to