Changeset 200067 in webkit


Ignore:
Timestamp:
Apr 25, 2016 6:00:17 PM (8 years ago)
Author:
Matt Baker
Message:

Web Inspector: hook up grid row filtering in the new Timelines UI
https://bugs.webkit.org/show_bug.cgi?id=154924
<rdar://problem/24934607>

Reviewed by Timothy Hatcher.

Re-implement timeline data grid filtering that previously existed in the
navigation sidebar. This patch adds support for filter text, scope bars,
and filtering based on ruler selection.

Multi-column filter support is now part of DataGrid. The grid checks compares
filter text against cell data of type string. DataGridNode subclasses may
provide custom string data for columns that format complex objects (such
as SourceCodeLocations). Cells containing data of type number are not
considered for filtering at this time.

  • UserInterface/Views/DataGrid.js:

(WebInspector.DataGrid):
(WebInspector.DataGrid.prototype.set filterText):
(WebInspector.DataGrid.prototype.get filterDelegate):
(WebInspector.DataGrid.prototype.set filterDelegate):
(WebInspector.DataGrid.prototype.filterDidChange):
Called internally by the grid whenever the filter text or delegate changes.
Also called by clients that implement a filter delegate, to inform the
grid that a custom filter has changed.

(WebInspector.DataGrid.prototype.hasCustomFilters):
(WebInspector.DataGrid.prototype.matchNodeAgainstCustomFilters):
Calls the filter delegate, if it exists, and provides a hook for
subclasses to provide custom filtering.

(WebInspector.DataGrid.prototype._applyFiltersToNode.matchTextFilter):
(WebInspector.DataGrid.prototype._applyFiltersToNode.makeVisible):
(WebInspector.DataGrid.prototype._applyFiltersToNode):
Filters data grid nodes and fires filter events as needed.
(WebInspector.DataGrid.prototype._hasFilterDelegate):
Helper function.
(WebInspector.DataGrid.prototype._updateVisibleRows):
Exclude hidden nodes from revealed rows.
(WebInspector.DataGrid.prototype._updateFilter):
Filtering entry point, called on an animation frame. Updates visible
rows if any node was filtered/unfiltered.

(WebInspector.DataGridNode):
(WebInspector.DataGridNode.prototype.get filterableData):
Gets an array of filterable strings for the node.
(WebInspector.DataGridNode.prototype.refresh):
Resets cached filterable strings.
(WebInspector.DataGridNode.prototype.filterableDataForColumn):
Can be overridden by subclasses to provide filterable text for complex
cell data, like as objects formatted as document fragments.

  • UserInterface/Views/LayoutTimelineDataGridNode.js:

(WebInspector.LayoutTimelineDataGridNode.prototype.get data):

  • UserInterface/Views/LayoutTimelineView.js:

(WebInspector.LayoutTimelineView):
Register grid and remove logic that has been moved to the base class.
(WebInspector.LayoutTimelineView.prototype.filterDidChange):
Update highlight after grid filter change.
(WebInspector.LayoutTimelineView.prototype._dataGridSelectedNodeChanged):
Update highlight when selection changes.
(WebInspector.LayoutTimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
(WebInspector.LayoutTimelineView.prototype.treeElementDeselected): Deleted.
(WebInspector.LayoutTimelineView.prototype._dataGridFiltersDidChange): Deleted.
(WebInspector.LayoutTimelineView.prototype._dataGridNodeSelected): Deleted.
No longer needed.

  • UserInterface/Views/NetworkTimelineView.js:

(WebInspector.NetworkTimelineView):
Register grid and remove logic that has been moved to the base class.
(WebInspector.NetworkTimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
(WebInspector.NetworkTimelineView.prototype._dataGridFiltersDidChange): Deleted.
(WebInspector.NetworkTimelineView.prototype._dataGridNodeSelected): Deleted.
No longer needed.

  • UserInterface/Views/OverviewTimelineView.js:

(WebInspector.OverviewTimelineView):
Register grid and remove logic that has been moved to the base class.
(WebInspector.OverviewTimelineView.prototype._dataGridNodeSelected): Deleted.
No longer needed.

  • UserInterface/Views/RenderingFrameTimelineView.js:

(WebInspector.RenderingFrameTimelineView):
Register grid and remove logic that has been moved to the base class.
(WebInspector.RenderingFrameTimelineView.prototype.get filterStartTime):
(WebInspector.RenderingFrameTimelineView.prototype.get filterEndTime):
Convert selection indices into filter start and end times.
(WebInspector.RenderingFrameTimelineView.prototype.matchDataGridNodeAgainstCustomFilters):
Perform custom filtering on rendering frame duration.
(WebInspector.RenderingFrameTimelineView.prototype._scopeBarSelectionDidChange):
Inform grid of custom filter change.
(WebInspector.RenderingFrameTimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
(WebInspector.RenderingFrameTimelineView.prototype._dataGridNodeSelected): Deleted.
No longer needed.

  • UserInterface/Views/ResourceTimelineDataGridNode.js:

(WebInspector.ResourceTimelineDataGridNode.prototype.filterableDataForColumn):
Use URL string for filtering "name" column.

  • UserInterface/Views/ScriptClusterTimelineView.js:

(WebInspector.ScriptClusterTimelineView.prototype.updateFilter):
Forwarding for TimelineView API.
(WebInspector.ScriptClusterTimelineView.prototype.matchDataGridNodeAgainstCustomFilters):
(WebInspector.ScriptClusterTimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
Renamed to matchDataGridNodeAgainstCustomFilters.
(WebInspector.ScriptClusterTimelineView.prototype._scriptClusterViewCurrentContentViewDidChange): Deleted.
Removed FIXME comment. Updating TimelineView times is sufficient to trigger filtering.

  • UserInterface/Views/ScriptDetailsTimelineView.js:

(WebInspector.ScriptDetailsTimelineView):
Register grid and remove logic that has been moved to the base class.
(WebInspector.ScriptDetailsTimelineView.prototype._dataGridFiltersDidChange): Deleted.
(WebInspector.ScriptDetailsTimelineView.prototype._dataGridNodeSelected): Deleted.
No longer needed.

  • UserInterface/Views/ScriptTimelineDataGridNode.js:

(WebInspector.ScriptTimelineDataGridNode.prototype.filterableDataForColumn):
Use main title and subtitle strings for filtering "name" column.
(WebInspector.ScriptTimelineDataGridNode.prototype._createNameCellDocumentFragment):
(WebInspector.ScriptTimelineDataGridNode.prototype._subtitle):
Break out for use in filterableDataForColumn.

  • UserInterface/Views/TimelineDataGrid.js:

(WebInspector.TimelineDataGrid):
Cleanup variable names.
(WebInspector.TimelineDataGrid.prototype.hasCustomFilters):
Always true because filtering on ruler selection always occurs.
(WebInspector.TimelineDataGrid.prototype.matchNodeAgainstCustomFilters):
Match nodes against scope bar filters.
(WebInspector.TimelineDataGrid.prototype._scopeBarSelectedItemsDidChange):
Inform grid of custom filter change.
(WebInspector.TimelineDataGrid.prototype.treeElementMatchesActiveScopeFilters): Deleted.
Re-implemented as _nodeMatchesActiveScopeFilters.
(WebInspector.TimelineDataGrid.prototype._updateScopeBarForcedVisibility): Deleted.
Old UI. No longer needed.

  • UserInterface/Views/TimelineDataGridNode.js:

(WebInspector.TimelineDataGridNode.prototype.filterableDataForColumn):
Filter strings for SourceCodeLocation and CallFrame objects.

  • UserInterface/Views/TimelineRecordingContentView.js:

(WebInspector.TimelineRecordingContentView):
Listen for FilterBar changes and TimelineView record filtering.
(WebInspector.TimelineRecordingContentView.prototype._filterDidChange):
Update grid filters when filter bar changes.
(WebInspector.TimelineRecordingContentView.prototype._recordWasFiltered):
Update overview when records are filtered/unfiltered.
(WebInspector.TimelineRecordingContentView.prototype.filterDidChange): Deleted.
(WebInspector.TimelineRecordingContentView.prototype.recordWasFiltered): Deleted.
(WebInspector.TimelineRecordingContentView.prototype.matchTreeElementAgainstCustomFilters.checkTimeBounds): Deleted.
(WebInspector.TimelineRecordingContentView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
Re-implemented in DataGrid.
(WebInspector.TimelineRecordingContentView.prototype._updateTimes): Deleted.
FIXME comment removed. Filtering occurs when TimelineView times are updated.
(WebInspector.TimelineRecordingContentView.prototype._timeRangeSelectionChanged): Deleted.

  • UserInterface/Views/TimelineView.js:

(WebInspector.TimelineView):
(WebInspector.TimelineView.prototype.get navigationItems):
Used by TimelineRecordingContentView to add scope bar items to the
lower content browser's navigation bar.

(WebInspector.TimelineView.prototype.set startTime):
(WebInspector.TimelineView.prototype.set endTime):
(WebInspector.TimelineView.prototype.set currentTime):
Update grid filter when recording times change.
(WebInspector.TimelineView.prototype.get filterStartTime):
(WebInspector.TimelineView.prototype.get filterEndTime):
Let subclasses (RenderingFrameTimelineView) provide filter start/end times.
(WebInspector.TimelineView.prototype.setupDataGrid):
Register the grid used by the TimelineView subclass, allowing the base
class to hook into common event listeners and provide boilerplate functionality.

(WebInspector.TimelineView.prototype.updateFilter):
For data grid views, updates grid filters and sets new filter text.
(WebInspector.TimelineView.prototype.matchDataGridNodeAgainstCustomFilters):
(WebInspector.TimelineView.prototype.dataGridMatchNodeAgainstCustomFilters.checkTimeBounds):
(WebInspector.TimelineView.prototype.dataGridMatchNodeAgainstCustomFilters):
DataGrid filter delegate. Lets subclasses apply custom filters first,
then filters based on ruler selection if needed.

(WebInspector.TimelineView.prototype.filterDidChange):
Hook for subclasses to respond to filter changes.
(WebInspector.TimelineView.prototype._filterTimesDidChange.delayedWork):
(WebInspector.TimelineView.prototype._filterTimesDidChange):
Helper function for coalescing ruler selection updates into a single
filter update.

(WebInspector.TimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
(WebInspector.TimelineView.prototype.filterUpdated): Deleted.
No longer needed.

Location:
trunk/Source/WebInspectorUI
Files:
15 edited

Legend:

Unmodified
Added
Removed
  • trunk/Source/WebInspectorUI/ChangeLog

    r200065 r200067  
     12016-04-25  Matt Baker  <mattbaker@apple.com>
     2
     3        Web Inspector: hook up grid row filtering in the new Timelines UI
     4        https://bugs.webkit.org/show_bug.cgi?id=154924
     5        <rdar://problem/24934607>
     6
     7        Reviewed by Timothy Hatcher.
     8
     9        Re-implement timeline data grid filtering that previously existed in the
     10        navigation sidebar. This patch adds support for filter text, scope bars,
     11        and filtering based on ruler selection.
     12
     13        Multi-column filter support is now part of DataGrid. The grid checks compares
     14        filter text against cell data of type string. DataGridNode subclasses may
     15        provide custom string data for columns that format complex objects (such
     16        as SourceCodeLocations). Cells containing data of type number are not
     17        considered for filtering at this time.
     18
     19        * UserInterface/Views/DataGrid.js:
     20        (WebInspector.DataGrid):
     21        (WebInspector.DataGrid.prototype.set filterText):
     22        (WebInspector.DataGrid.prototype.get filterDelegate):
     23        (WebInspector.DataGrid.prototype.set filterDelegate):
     24        (WebInspector.DataGrid.prototype.filterDidChange):
     25        Called internally by the grid whenever the filter text or delegate changes.
     26        Also called by clients that implement a filter delegate, to inform the
     27        grid that a custom filter has changed.
     28
     29        (WebInspector.DataGrid.prototype.hasCustomFilters):
     30        (WebInspector.DataGrid.prototype.matchNodeAgainstCustomFilters):
     31        Calls the filter delegate, if it exists, and provides a hook for
     32        subclasses to provide custom filtering.
     33
     34        (WebInspector.DataGrid.prototype._applyFiltersToNode.matchTextFilter):
     35        (WebInspector.DataGrid.prototype._applyFiltersToNode.makeVisible):
     36        (WebInspector.DataGrid.prototype._applyFiltersToNode):
     37        Filters data grid nodes and fires filter events as needed.
     38        (WebInspector.DataGrid.prototype._hasFilterDelegate):
     39        Helper function.
     40        (WebInspector.DataGrid.prototype._updateVisibleRows):
     41        Exclude hidden nodes from revealed rows.
     42        (WebInspector.DataGrid.prototype._updateFilter):
     43        Filtering entry point, called on an animation frame. Updates visible
     44        rows if any node was filtered/unfiltered.
     45
     46        (WebInspector.DataGridNode):
     47        (WebInspector.DataGridNode.prototype.get filterableData):
     48        Gets an array of filterable strings for the node.
     49        (WebInspector.DataGridNode.prototype.refresh):
     50        Resets cached filterable strings.
     51        (WebInspector.DataGridNode.prototype.filterableDataForColumn):
     52        Can be overridden by subclasses to provide filterable text for complex
     53        cell data, like as objects formatted as document fragments.
     54
     55        * UserInterface/Views/LayoutTimelineDataGridNode.js:
     56        (WebInspector.LayoutTimelineDataGridNode.prototype.get data):
     57
     58        * UserInterface/Views/LayoutTimelineView.js:
     59        (WebInspector.LayoutTimelineView):
     60        Register grid and remove logic that has been moved to the base class.
     61        (WebInspector.LayoutTimelineView.prototype.filterDidChange):
     62        Update highlight after grid filter change.
     63        (WebInspector.LayoutTimelineView.prototype._dataGridSelectedNodeChanged):
     64        Update highlight when selection changes.
     65        (WebInspector.LayoutTimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
     66        (WebInspector.LayoutTimelineView.prototype.treeElementDeselected): Deleted.
     67        (WebInspector.LayoutTimelineView.prototype._dataGridFiltersDidChange): Deleted.
     68        (WebInspector.LayoutTimelineView.prototype._dataGridNodeSelected): Deleted.
     69        No longer needed.
     70
     71        * UserInterface/Views/NetworkTimelineView.js:
     72        (WebInspector.NetworkTimelineView):
     73        Register grid and remove logic that has been moved to the base class.
     74        (WebInspector.NetworkTimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
     75        (WebInspector.NetworkTimelineView.prototype._dataGridFiltersDidChange): Deleted.
     76        (WebInspector.NetworkTimelineView.prototype._dataGridNodeSelected): Deleted.
     77        No longer needed.
     78
     79        * UserInterface/Views/OverviewTimelineView.js:
     80        (WebInspector.OverviewTimelineView):
     81        Register grid and remove logic that has been moved to the base class.
     82        (WebInspector.OverviewTimelineView.prototype._dataGridNodeSelected): Deleted.
     83        No longer needed.
     84
     85        * UserInterface/Views/RenderingFrameTimelineView.js:
     86        (WebInspector.RenderingFrameTimelineView):
     87        Register grid and remove logic that has been moved to the base class.
     88        (WebInspector.RenderingFrameTimelineView.prototype.get filterStartTime):
     89        (WebInspector.RenderingFrameTimelineView.prototype.get filterEndTime):
     90        Convert selection indices into filter start and end times.
     91        (WebInspector.RenderingFrameTimelineView.prototype.matchDataGridNodeAgainstCustomFilters):
     92        Perform custom filtering on rendering frame duration.
     93        (WebInspector.RenderingFrameTimelineView.prototype._scopeBarSelectionDidChange):
     94        Inform grid of custom filter change.
     95        (WebInspector.RenderingFrameTimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
     96        (WebInspector.RenderingFrameTimelineView.prototype._dataGridNodeSelected): Deleted.
     97        No longer needed.
     98
     99        * UserInterface/Views/ResourceTimelineDataGridNode.js:
     100        (WebInspector.ResourceTimelineDataGridNode.prototype.filterableDataForColumn):
     101        Use URL string for filtering "name" column.
     102
     103        * UserInterface/Views/ScriptClusterTimelineView.js:
     104        (WebInspector.ScriptClusterTimelineView.prototype.updateFilter):
     105        Forwarding for TimelineView API.
     106        (WebInspector.ScriptClusterTimelineView.prototype.matchDataGridNodeAgainstCustomFilters):
     107        (WebInspector.ScriptClusterTimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
     108        Renamed to matchDataGridNodeAgainstCustomFilters.
     109        (WebInspector.ScriptClusterTimelineView.prototype._scriptClusterViewCurrentContentViewDidChange): Deleted.
     110        Removed FIXME comment. Updating TimelineView times is sufficient to trigger filtering.
     111
     112        * UserInterface/Views/ScriptDetailsTimelineView.js:
     113        (WebInspector.ScriptDetailsTimelineView):
     114        Register grid and remove logic that has been moved to the base class.
     115        (WebInspector.ScriptDetailsTimelineView.prototype._dataGridFiltersDidChange): Deleted.
     116        (WebInspector.ScriptDetailsTimelineView.prototype._dataGridNodeSelected): Deleted.
     117        No longer needed.
     118
     119        * UserInterface/Views/ScriptTimelineDataGridNode.js:
     120        (WebInspector.ScriptTimelineDataGridNode.prototype.filterableDataForColumn):
     121        Use main title and subtitle strings for filtering "name" column.
     122        (WebInspector.ScriptTimelineDataGridNode.prototype._createNameCellDocumentFragment):
     123        (WebInspector.ScriptTimelineDataGridNode.prototype._subtitle):
     124        Break out for use in filterableDataForColumn.
     125
     126        * UserInterface/Views/TimelineDataGrid.js:
     127        (WebInspector.TimelineDataGrid):
     128        Cleanup variable names.
     129        (WebInspector.TimelineDataGrid.prototype.hasCustomFilters):
     130        Always true because filtering on ruler selection always occurs.
     131        (WebInspector.TimelineDataGrid.prototype.matchNodeAgainstCustomFilters):
     132        Match nodes against scope bar filters.
     133        (WebInspector.TimelineDataGrid.prototype._scopeBarSelectedItemsDidChange):
     134        Inform grid of custom filter change.
     135        (WebInspector.TimelineDataGrid.prototype.treeElementMatchesActiveScopeFilters): Deleted.
     136        Re-implemented as _nodeMatchesActiveScopeFilters.
     137        (WebInspector.TimelineDataGrid.prototype._updateScopeBarForcedVisibility): Deleted.
     138        Old UI. No longer needed.
     139
     140        * UserInterface/Views/TimelineDataGridNode.js:
     141        (WebInspector.TimelineDataGridNode.prototype.filterableDataForColumn):
     142        Filter strings for SourceCodeLocation and CallFrame objects.
     143
     144        * UserInterface/Views/TimelineRecordingContentView.js:
     145        (WebInspector.TimelineRecordingContentView):
     146        Listen for FilterBar changes and TimelineView record filtering.
     147        (WebInspector.TimelineRecordingContentView.prototype._filterDidChange):
     148        Update grid filters when filter bar changes.
     149        (WebInspector.TimelineRecordingContentView.prototype._recordWasFiltered):
     150        Update overview when records are filtered/unfiltered.
     151        (WebInspector.TimelineRecordingContentView.prototype.filterDidChange): Deleted.
     152        (WebInspector.TimelineRecordingContentView.prototype.recordWasFiltered): Deleted.
     153        (WebInspector.TimelineRecordingContentView.prototype.matchTreeElementAgainstCustomFilters.checkTimeBounds): Deleted.
     154        (WebInspector.TimelineRecordingContentView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
     155        Re-implemented in DataGrid.
     156        (WebInspector.TimelineRecordingContentView.prototype._updateTimes): Deleted.
     157        FIXME comment removed. Filtering occurs when TimelineView times are updated.
     158        (WebInspector.TimelineRecordingContentView.prototype._timeRangeSelectionChanged): Deleted.
     159
     160        * UserInterface/Views/TimelineView.js:
     161        (WebInspector.TimelineView):
     162        (WebInspector.TimelineView.prototype.get navigationItems):
     163        Used by TimelineRecordingContentView to add scope bar items to the
     164        lower content browser's navigation bar.
     165
     166        (WebInspector.TimelineView.prototype.set startTime):
     167        (WebInspector.TimelineView.prototype.set endTime):
     168        (WebInspector.TimelineView.prototype.set currentTime):
     169        Update grid filter when recording times change.
     170        (WebInspector.TimelineView.prototype.get filterStartTime):
     171        (WebInspector.TimelineView.prototype.get filterEndTime):
     172        Let subclasses (RenderingFrameTimelineView) provide filter start/end times.
     173        (WebInspector.TimelineView.prototype.setupDataGrid):
     174        Register the grid used by the TimelineView subclass, allowing the base
     175        class to hook into common event listeners and provide boilerplate functionality.
     176
     177        (WebInspector.TimelineView.prototype.updateFilter):
     178        For data grid views, updates grid filters and sets new filter text.
     179        (WebInspector.TimelineView.prototype.matchDataGridNodeAgainstCustomFilters):
     180        (WebInspector.TimelineView.prototype.dataGridMatchNodeAgainstCustomFilters.checkTimeBounds):
     181        (WebInspector.TimelineView.prototype.dataGridMatchNodeAgainstCustomFilters):
     182        DataGrid filter delegate. Lets subclasses apply custom filters first,
     183        then filters based on ruler selection if needed.
     184
     185        (WebInspector.TimelineView.prototype.filterDidChange):
     186        Hook for subclasses to respond to filter changes.
     187        (WebInspector.TimelineView.prototype._filterTimesDidChange.delayedWork):
     188        (WebInspector.TimelineView.prototype._filterTimesDidChange):
     189        Helper function for coalescing ruler selection updates into a single
     190        filter update.
     191
     192        (WebInspector.TimelineView.prototype.matchTreeElementAgainstCustomFilters): Deleted.
     193        (WebInspector.TimelineView.prototype.filterUpdated): Deleted.
     194        No longer needed.
     195
    11962016-04-25  Joseph Pecoraro  <pecoraro@apple.com>
    2197
  • trunk/Source/WebInspectorUI/UserInterface/Views/DataGrid.js

    r199972 r200067  
    5454        this._columnWidthsInitialized = false;
    5555
     56        this._filterText = "";
     57        this._filterDelegate = null;
     58
    5659        this.element.className = "data-grid";
    5760        this.element.tabIndex = 0;
     
    282285    }
    283286
     287    set filterText(x)
     288    {
     289        if (this._filterText === x)
     290            return;
     291
     292        this._filterText = x;
     293        this.filterDidChange();
     294    }
     295
     296    get filterDelegate() { return this._filterDelegate; }
     297
     298    set filterDelegate(delegate)
     299    {
     300        this._filterDelegate = delegate;
     301        this.filterDidChange();
     302    }
     303
     304    filterDidChange()
     305    {
     306        if (this._scheduledFilterUpdateIdentifier)
     307            return;
     308
     309        this._scheduledFilterUpdateIdentifier = requestAnimationFrame(this._updateFilter.bind(this));
     310    }
     311
     312    hasCustomFilters()
     313    {
     314        return this._hasFilterDelegate();
     315    }
     316
     317    matchNodeAgainstCustomFilters(node)
     318    {
     319        if (!this._hasFilterDelegate())
     320            return true;
     321        return this._filterDelegate.dataGridMatchNodeAgainstCustomFilters(node);
     322    }
     323
     324    _applyFiltersToNode(node)
     325    {
     326        if (!this._textFilterRegex && !this.hasCustomFilters()) {
     327            // No filters, so make everything visible.
     328            node.hidden = false;
     329
     330            // If the node was expanded during filtering, collapse it again.
     331            if (node.expanded && node[WebInspector.DataGrid.WasExpandedDuringFilteringSymbol]) {
     332                node[WebInspector.DataGrid.WasExpandedDuringFilteringSymbol] = false;
     333                node.collapse();
     334            }
     335
     336            return;
     337        }
     338
     339        let filterableData = node.filterableData || [];
     340        let flags = {expandNode: false};
     341        let filterRegex = this._textFilterRegex;
     342
     343        function matchTextFilter()
     344        {
     345            if (!filterableData.length || !filterRegex)
     346                return true;
     347
     348            if (filterableData.some((value) => filterRegex.test(value))) {
     349                flags.expandNode = true;
     350                return true;
     351            }
     352
     353            return false;
     354        }
     355
     356        function makeVisible()
     357        {
     358            // Make this element visible.
     359            node.hidden = false;
     360
     361            // Make the ancestors visible and expand them.
     362            let currentAncestor = node.parent;
     363            while (currentAncestor && !currentAncestor.root) {
     364                currentAncestor.hidden = false;
     365
     366                // Only expand if the built-in filters matched, not custom filters.
     367                if (flags.expandNode && !currentAncestor.expanded) {
     368                    currentAncestor[WebInspector.DataGrid.WasExpandedDuringFilteringSymbol] = true;
     369                    currentAncestor.expand();
     370                }
     371
     372                currentAncestor = currentAncestor.parent;
     373            }
     374        }
     375
     376        if (matchTextFilter() && this.matchNodeAgainstCustomFilters(node)) {
     377            // Make the node visible since it matches.
     378            makeVisible();
     379
     380            // If the node didn't match a built-in filter and was expanded earlier during filtering, collapse it again.
     381            if (!flags.expandNode && node.expanded && node[WebInspector.DataGrid.WasExpandedDuringFilteringSymbol]) {
     382                node[WebInspector.DataGrid.WasExpandedDuringFilteringSymbol] = false;
     383                node.collapse();
     384            }
     385
     386            return;
     387        }
     388
     389        // Make the node invisible since it does not match.
     390        node.hidden = true;
     391    }
     392
    284393    _updateSortedColumn(oldSortColumnIdentifier)
    285394    {
     
    300409
    301410        this.dispatchEventToListeners(WebInspector.DataGrid.Event.SortChanged);
     411    }
     412
     413    _hasFilterDelegate()
     414    {
     415        return this._filterDelegate && typeof this._filterDelegate.dataGridMatchNodeAgainstCustomFilters === "function";
    302416    }
    303417
     
    868982        let updateOffsetThreshold = rowHeight * 5;
    869983
    870         let revealedRows = this._rows.filter((row) => row.revealed);
     984        let revealedRows = this._rows.filter((row) => row.revealed && !row.hidden);
    871985
    872986        let scrollTop = this._scrollContainerElement.scrollTop;
     
    15701684        this._currentResizer = null;
    15711685    }
     1686
     1687    _updateFilter()
     1688    {
     1689        if (this._scheduledFilterUpdateIdentifier) {
     1690            cancelAnimationFrame(this._scheduledFilterUpdateIdentifier);
     1691            this._scheduledFilterUpdateIdentifier = undefined;
     1692        }
     1693
     1694        if (!this._rows.length)
     1695            return;
     1696
     1697        this._textFilterRegex = simpleGlobStringToRegExp(this._filterText, "i");
     1698
     1699        // Don't populate if we don't have any active filters.
     1700        // We only need to populate when a filter needs to reveal.
     1701        let dontPopulate = !this._textFilterRegex && !this.hasCustomFilters();
     1702
     1703        let filterDidModifyNode = false;
     1704        let currentNode = this._rows[0];
     1705        while (currentNode && !currentNode.root) {
     1706            const currentNodeWasHidden = currentNode.hidden;
     1707            this._applyFiltersToNode(currentNode);
     1708            if (currentNodeWasHidden !== currentNode.hidden) {
     1709                this.dispatchEventToListeners(WebInspector.DataGrid.Event.NodeWasFiltered, {node: currentNode});
     1710                filterDidModifyNode = true;
     1711            }
     1712
     1713            currentNode = currentNode.traverseNextNode(false, null, dontPopulate);
     1714        }
     1715
     1716        if (!filterDidModifyNode)
     1717            return;
     1718
     1719        this._updateVisibleRows();
     1720        this.dispatchEventToListeners(WebInspector.DataGrid.Event.FilterDidChange);
     1721    }
    15721722};
    15731723
     
    15761726    SelectedNodeChanged: "datagrid-selected-node-changed",
    15771727    ExpandedNode: "datagrid-expanded-node",
    1578     CollapsedNode: "datagrid-collapsed-node"
     1728    CollapsedNode: "datagrid-collapsed-node",
     1729    FilterDidChange: "datagrid-filter-did-change",
     1730    NodeWasFiltered: "datagrid-node-was-filtered"
    15791731};
    15801732
     
    15931745WebInspector.DataGrid.PreviousColumnOrdinalSymbol = Symbol("previous-column-ordinal");
    15941746WebInspector.DataGrid.NextColumnOrdinalSymbol = Symbol("next-column-ordinal");
     1747WebInspector.DataGrid.WasExpandedDuringFilteringSymbol = Symbol("was-expanded-during-filtering");
    15951748
    15961749WebInspector.DataGrid.ColumnResizePadding = 10;
     
    17271880    }
    17281881
     1882    get filterableData()
     1883    {
     1884        if (this._cachedFilterableData)
     1885            return this._cachedFilterableData;
     1886
     1887        this._cachedFilterableData = [];
     1888
     1889        for (let column of this.dataGrid.columns.values()) {
     1890            let value = this.filterableDataForColumn(column.columnIdentifier);
     1891            if (!value)
     1892                continue;
     1893
     1894            if (!(value instanceof Array))
     1895                value = [value];
     1896
     1897            if (!value.length)
     1898                continue;
     1899
     1900            this._cachedFilterableData = this._cachedFilterableData.concat(value);
     1901        }
     1902
     1903        return this._cachedFilterableData;
     1904    }
     1905
    17291906    get revealed()
    17301907    {
     
    18572034        }
    18582035
     2036        this._cachedFilterableData = null;
    18592037        this._needsRefresh = false;
    18602038
     
    22552433        return null;
    22562434    }
     2435
     2436    // Protected
     2437
     2438    filterableDataForColumn(columnIdentifier)
     2439    {
     2440        let value = this.data[columnIdentifier];
     2441        return typeof value === "string" ? value : null;
     2442    }
    22572443};
    22582444
  • trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineDataGridNode.js

    r199635 r200067  
    4545        if (!this._cachedData) {
    4646            this._cachedData = {
     47                type: this._record.eventType,
    4748                name: this.displayName(),
    4849                width: this._record.width,
  • trunk/Source/WebInspectorUI/UserInterface/Views/LayoutTimelineView.js

    r199634 r200067  
    3232        console.assert(timeline.type === WebInspector.TimelineRecord.Type.Layout, timeline);
    3333
    34         let columns = {name: {}, location: {}, width: {}, height: {}, startTime: {}, totalTime: {}};
     34        let columns = {type: {}, name: {}, location: {}, width: {}, height: {}, startTime: {}, totalTime: {}};
    3535
    3636        columns.name.title = WebInspector.UIString("Type");
     
    4343        }
    4444
    45         columns.name.scopeBar = WebInspector.TimelineDataGrid.createColumnScopeBar("layout", typeToLabelMap);
     45        columns.type.scopeBar = WebInspector.TimelineDataGrid.createColumnScopeBar("layout", typeToLabelMap);
     46        columns.type.hidden = true;
     47
    4648        columns.name.disclosure = true;
    4749        columns.name.icon = true;
    4850
    49         this._scopeBar = columns.name.scopeBar;
     51        this._scopeBar = columns.type.scopeBar;
    5052
    5153        columns.location.title = WebInspector.UIString("Initiator");
     
    7072
    7173        this._dataGrid = new WebInspector.LayoutTimelineDataGrid(columns);
    72         this._dataGrid.addEventListener(WebInspector.TimelineDataGrid.Event.FiltersDidChange, this._dataGridFiltersDidChange, this);
    73         this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
     74        this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridSelectedNodeChanged, this);
     75
     76        this.setupDataGrid(this._dataGrid);
    7477
    7578        this._dataGrid.sortColumnIdentifierSetting = new WebInspector.Setting("layout-timeline-view-sort", "startTime");
     
    142145    }
    143146
    144     filterDidChange()
    145     {
    146         super.filterDidChange();
    147 
    148         this._updateHighlight();
    149     }
    150 
    151     matchTreeElementAgainstCustomFilters(treeElement)
    152     {
    153         return this._dataGrid.treeElementMatchesActiveScopeFilters(treeElement);
    154     }
    155 
    156147    reset()
    157148    {
     
    175166    }
    176167
    177     treeElementDeselected(treeElement)
    178     {
    179         super.treeElementDeselected(treeElement);
     168    filterDidChange()
     169    {
     170        super.filterDidChange();
    180171
    181172        this._updateHighlight();
     
    247238    }
    248239
    249     _dataGridFiltersDidChange(event)
    250     {
    251         // FIXME: <https://webkit.org/b/154924> Web Inspector: hook up grid row filtering in the new Timelines UI
    252     }
    253 
    254     _dataGridNodeSelected(event)
    255     {
    256         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
    257     }
    258 
    259240    _updateHighlight()
    260241    {
     
    328309        this._updateHighlight();
    329310    }
     311
     312    _dataGridSelectedNodeChanged(event)
     313    {
     314        this._updateHighlight();
     315    }
    330316};
  • trunk/Source/WebInspectorUI/UserInterface/Views/NetworkTimelineView.js

    r199974 r200067  
    8989
    9090        this._dataGrid = new WebInspector.TimelineDataGrid(columns);
    91         this._dataGrid.addEventListener(WebInspector.TimelineDataGrid.Event.FiltersDidChange, this._dataGridFiltersDidChange, this);
    92         this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
    9391        this._dataGrid.sortDelegate = this;
    9492        this._dataGrid.sortColumnIdentifierSetting = new WebInspector.Setting("network-timeline-view-sort", "requestSent");
    9593        this._dataGrid.sortOrderSetting = new WebInspector.Setting("network-timeline-view-sort-order", WebInspector.DataGrid.SortOrder.Ascending);
    9694
     95        this.setupDataGrid(this._dataGrid);
     96
    9797        this.element.classList.add("network");
    9898        this.addSubview(this._dataGrid);
     
    138138
    139139        this._dataGrid.closed();
    140     }
    141 
    142     matchTreeElementAgainstCustomFilters(treeElement)
    143     {
    144         return this._dataGrid.treeElementMatchesActiveScopeFilters(treeElement);
    145140    }
    146141
     
    236231        this.needsLayout();
    237232    }
    238 
    239     _dataGridFiltersDidChange(event)
    240     {
    241         // FIXME: <https://webkit.org/b/154924> Web Inspector: hook up grid row filtering in the new Timelines UI
    242     }
    243 
    244     _dataGridNodeSelected(event)
    245     {
    246         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
    247     }
    248233};
  • trunk/Source/WebInspectorUI/UserInterface/Views/OverviewTimelineView.js

    r199241 r200067  
    4646
    4747        this._dataGrid = new WebInspector.DataGrid(columns);
    48         this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
     48
     49        this.setupDataGrid(this._dataGrid);
    4950
    5051        this._currentTimeMarker = new WebInspector.TimelineMarker(0, WebInspector.TimelineMarker.Type.CurrentTime);
     
    295296    }
    296297
    297     _dataGridNodeSelected(event)
    298     {
    299         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
    300     }
    301 
    302298    _recordingReset(event)
    303299    {
  • trunk/Source/WebInspectorUI/UserInterface/Views/RenderingFrameTimelineView.js

    r199634 r200067  
    7878
    7979        this._dataGrid = new WebInspector.TimelineDataGrid(columns);
    80         this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
    8180        this._dataGrid.sortColumnIdentifierSetting = new WebInspector.Setting("rendering-frame-timeline-view-sort", "startTime");
    8281        this._dataGrid.sortOrderSetting = new WebInspector.Setting("rendering-frame-timeline-view-sort-order", WebInspector.DataGrid.SortOrder.Ascending);
     82
     83        this.setupDataGrid(this._dataGrid);
    8384
    8485        this.element.classList.add("rendering-frame");
     
    152153    }
    153154
    154     matchTreeElementAgainstCustomFilters(treeElement)
    155     {
    156         console.assert(this._scopeBar.selectedItems.length === 1);
    157         var selectedScopeBarItem = this._scopeBar.selectedItems[0];
    158         if (!selectedScopeBarItem || selectedScopeBarItem.id === WebInspector.RenderingFrameTimelineView.DurationFilter.All)
    159             return true;
    160 
    161         while (treeElement && !(treeElement.record instanceof WebInspector.RenderingFrameTimelineRecord))
    162             treeElement = treeElement.parent;
    163 
    164         console.assert(treeElement, "Cannot apply duration filter: no RenderingFrameTimelineRecord found.");
    165         if (!treeElement)
    166             return false;
    167 
    168         var minimumDuration = selectedScopeBarItem.id === WebInspector.RenderingFrameTimelineView.DurationFilter.OverOneMillisecond ? 0.001 : 0.015;
    169         return treeElement.record.duration > minimumDuration;
     155    get filterStartTime()
     156    {
     157        let records = this.representedObject.records;
     158        let startIndex = this.startTime;
     159        if (startIndex >= records.length)
     160            return Infinity;
     161
     162        return records[startIndex].startTime;
     163    }
     164
     165    get filterEndTime()
     166    {
     167        let records = this.representedObject.records;
     168        let endIndex = this.endTime - 1;
     169        if (endIndex >= records.length)
     170            return Infinity;
     171
     172        return records[endIndex].endTime;
    170173    }
    171174
     
    194197            return new WebInspector.ProfileNodeDataGridNode(treeElement.profileNode, this.zeroTime, this.startTime, this.endTime);
    195198        return null;
     199    }
     200
     201    matchDataGridNodeAgainstCustomFilters(node)
     202    {
     203        if (!super.matchDataGridNodeAgainstCustomFilters(node))
     204            return false;
     205
     206        console.assert(node instanceof WebInspector.TimelineDataGridNode);
     207        console.assert(this._scopeBar.selectedItems.length === 1);
     208        let selectedScopeBarItem = this._scopeBar.selectedItems[0];
     209        if (!selectedScopeBarItem || selectedScopeBarItem.id === WebInspector.RenderingFrameTimelineView.DurationFilter.All)
     210            return true;
     211
     212        while (node && !(node.record instanceof WebInspector.RenderingFrameTimelineRecord))
     213            node = node.parent;
     214
     215        console.assert(node, "Cannot apply duration filter: no RenderingFrameTimelineRecord found.");
     216        if (!node)
     217            return false;
     218
     219        let minimumDuration = selectedScopeBarItem.id === WebInspector.RenderingFrameTimelineView.DurationFilter.OverOneMillisecond ? 0.001 : 0.015;
     220        return node.record.duration > minimumDuration;
    196221    }
    197222
     
    265290    }
    266291
    267     _dataGridNodeSelected(event)
    268     {
    269         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
    270     }
    271 
    272     _scopeBarSelectionDidChange(event)
    273     {
    274         // FIXME: <https://webkit.org/b/154924> Web Inspector: hook up grid row filtering in the new Timelines UI
     292    _scopeBarSelectionDidChange()
     293    {
     294        this.filterDidChange();
    275295    }
    276296};
  • trunk/Source/WebInspectorUI/UserInterface/Views/ResourceTimelineDataGridNode.js

    r197909 r200067  
    147147    }
    148148
     149    // Protected
     150
     151    filterableDataForColumn(columnIdentifier)
     152    {
     153        if (columnIdentifier === "name")
     154            return this._resource.url;
     155        return super.filterableDataForColumn(columnIdentifier);
     156    }
     157
    149158    // Private
    150159
  • trunk/Source/WebInspectorUI/UserInterface/Views/ScriptClusterTimelineView.js

    r198601 r200067  
    7272    get navigationSidebarTreeOutline() { return this._contentViewContainer.currentContentView.navigationSidebarTreeOutline; }
    7373    reset() { return this._contentViewContainer.currentContentView.reset(); }
     74    updateFilter(filters) { return this._contentViewContainer.currentContentView.updateFilter(filters); }
    7475    filterDidChange() { return this._contentViewContainer.currentContentView.filterDidChange(); }
    75     matchTreeElementAgainstCustomFilters(treeElement) { return this._contentViewContainer.currentContentView.matchTreeElementAgainstCustomFilters(treeElement); }
     76    matchDataGridNodeAgainstCustomFilters(node) { return this._contentViewContainer.currentContentView.matchDataGridNodeAgainstCustomFilters(node); }
    7677
    7778    // Public
     
    197198        currentContentView.endTime = previousContentView.endTime;
    198199        currentContentView.currentTime = previousContentView.currentTime;
    199 
    200         // FIXME: <https://webkit.org/b/154924> Web Inspector: hook up grid row filtering in the new Timelines UI
    201200    }
    202201};
  • trunk/Source/WebInspectorUI/UserInterface/Views/ScriptDetailsTimelineView.js

    r199974 r200067  
    7373
    7474        this._dataGrid = new WebInspector.ScriptTimelineDataGrid(columns);
    75         this._dataGrid.addEventListener(WebInspector.TimelineDataGrid.Event.FiltersDidChange, this._dataGridFiltersDidChange, this);
    76         this._dataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, this._dataGridNodeSelected, this);
    7775        this._dataGrid.sortDelegate = this;
    7876        this._dataGrid.sortColumnIdentifierSetting = new WebInspector.Setting("script-timeline-view-sort", "startTime");
    7977        this._dataGrid.sortOrderSetting = new WebInspector.Setting("script-timeline-view-sort-order", WebInspector.DataGrid.SortOrder.Ascending);
     78
     79        this.setupDataGrid(this._dataGrid);
    8080
    8181        this.element.classList.add("script");
     
    237237        this.needsLayout();
    238238    }
    239 
    240     _dataGridFiltersDidChange(event)
    241     {
    242         // FIXME: <https://webkit.org/b/154924> Web Inspector: hook up grid row filtering in the new Timelines UI
    243     }
    244 
    245     _dataGridNodeSelected(event)
    246     {
    247         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
    248     }
    249239};
  • trunk/Source/WebInspectorUI/UserInterface/Views/ScriptTimelineDataGridNode.js

    r199974 r200067  
    157157    }
    158158
     159    // Protected
     160
     161    filterableDataForColumn(columnIdentifier)
     162    {
     163        if (columnIdentifier === "name")
     164            return [this.displayName(), this.subtitle];
     165
     166        return super.filterableDataForColumn(columnIdentifier);
     167    }
     168
    159169    // Private
    160170
  • trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGrid.js

    r199974 r200067  
    2626WebInspector.TimelineDataGrid = class TimelineDataGrid extends WebInspector.DataGrid
    2727{
    28     constructor(columns, treeOutline, delegate, editCallback, deleteCallback)
     28    constructor(columns, treeOutline, synchronizerDelegate, editCallback, deleteCallback)
    2929    {
    3030        super(columns, editCallback, deleteCallback);
    3131
    3232        if (treeOutline)
    33             this._treeOutlineDataGridSynchronizer = new WebInspector.TreeOutlineDataGridSynchronizer(treeOutline, this, delegate);
     33            this._treeOutlineDataGridSynchronizer = new WebInspector.TreeOutlineDataGridSynchronizer(treeOutline, this, synchronizerDelegate);
    3434
    3535        this.element.classList.add("timeline");
    3636
    37         this._filterableColumns = [];
    3837        this._sortDelegate = null;
     38        this._scopeBarColumns = [];
    3939
    4040        // Check if any of the cells can be filtered.
     
    4545                continue;
    4646
    47             this._filterableColumns.push(identifier);
     47            this._scopeBarColumns.push(identifier);
    4848            scopeBar.columnIdentifier = identifier;
    4949            scopeBar.addEventListener(WebInspector.ScopeBar.Event.SelectionChanged, this._scopeBarSelectedItemsDidChange, this);
    5050        }
    5151
    52         if (this._filterableColumns.length > 1) {
     52        if (this._scopeBarColumns.length > 1) {
    5353            console.error("Creating a TimelineDataGrid with more than one filterable column is not yet supported.");
    5454            return;
     
    150150    }
    151151
    152     treeElementMatchesActiveScopeFilters(treeElement)
    153     {
    154         if (!this._treeOutlineDataGridSynchronizer)
    155             return false;
    156 
    157         var dataGridNode = this._treeOutlineDataGridSynchronizer.dataGridNodeForTreeElement(treeElement);
    158         console.assert(dataGridNode);
    159 
    160         for (var identifier of this._filterableColumns) {
    161             var scopeBar = this.columns.get(identifier).scopeBar;
    162             if (!scopeBar || scopeBar.defaultItem.selected)
    163                 continue;
    164 
    165             var value = dataGridNode.data[identifier];
    166             var matchesFilter = scopeBar.selectedItems.some(function(scopeBarItem) {
    167                 return scopeBarItem.value === value;
    168             });
    169 
    170             if (!matchesFilter)
    171                 return false;
    172         }
    173 
    174         return true;
    175     }
    176 
    177152    addRowInSortOrder(treeElement, dataGridNode, parentTreeElementOrDataGridNode)
    178153    {
     
    234209
    235210        this._scheduledDataGridNodeRefreshIdentifier = requestAnimationFrame(this._refreshDirtyDataGridNodes.bind(this));
     211    }
     212
     213    hasCustomFilters()
     214    {
     215        return true;
     216    }
     217
     218    matchNodeAgainstCustomFilters(node)
     219    {
     220        if (!super.matchNodeAgainstCustomFilters(node))
     221            return false;
     222
     223        for (let identifier of this._scopeBarColumns) {
     224            let scopeBar = this.columns.get(identifier).scopeBar;
     225            if (!scopeBar || scopeBar.defaultItem.selected)
     226                continue;
     227
     228            let value = node.data[identifier];
     229            if (!scopeBar.selectedItems.some((scopeBarItem) => scopeBarItem.value === value))
     230                return false;
     231        }
     232
     233        return true;
    236234    }
    237235
     
    421419    }
    422420
    423     _updateScopeBarForcedVisibility()
    424     {
    425         for (var identifier of this._filterableColumns) {
    426             var scopeBar = this.columns.get(identifier).scopeBar;
    427             if (scopeBar) {
    428                 this.element.classList.toggle(WebInspector.TimelineDataGrid.HasNonDefaultFilterStyleClassName, scopeBar.hasNonDefaultItemSelected());
    429                 break;
    430             }
    431         }
    432     }
    433 
    434421    _scopeBarSelectedItemsDidChange(event)
    435422    {
    436         this._updateScopeBarForcedVisibility();
    437 
    438         var columnIdentifier = event.target.columnIdentifier;
    439         this.dispatchEventToListeners(WebInspector.TimelineDataGrid.Event.FiltersDidChange, {columnIdentifier});
     423        this.filterDidChange();
    440424    }
    441425
     
    565549};
    566550
     551WebInspector.TimelineDataGrid.WasExpandedDuringFilteringSymbol = Symbol("was-expanded-during-filtering");
     552
    567553WebInspector.TimelineDataGrid.HasNonDefaultFilterStyleClassName = "has-non-default-filter";
    568554WebInspector.TimelineDataGrid.DelayedPopoverShowTimeout = 250;
    569555WebInspector.TimelineDataGrid.DelayedPopoverHideContentClearTimeout = 500;
    570 
    571 WebInspector.TimelineDataGrid.Event = {
    572     FiltersDidChange: "timelinedatagrid-filters-did-change"
    573 };
    574 
  • trunk/Source/WebInspectorUI/UserInterface/Views/TimelineDataGridNode.js

    r197909 r200067  
    365365        return true;
    366366    }
     367
     368    filterableDataForColumn(columnIdentifier)
     369    {
     370        let value = this.data[columnIdentifier];
     371        if (value instanceof WebInspector.SourceCodeLocation)
     372            return value.displayLocationString();
     373
     374        if (value instanceof WebInspector.CallFrame)
     375            return [value.functionName, value.sourceCodeLocation.displayLocationString()];
     376
     377        return super.filterableDataForColumn(columnIdentifier);
     378    }
    367379};
  • trunk/Source/WebInspectorUI/UserInterface/Views/TimelineRecordingContentView.js

    r199972 r200067  
    5454        this._filterBarNavigationItem = new WebInspector.FilterBarNavigationItem;
    5555        this._filterBarNavigationItem.filterBar.placeholder = WebInspector.UIString("Filter Records");
     56        this._filterBarNavigationItem.filterBar.addEventListener(WebInspector.FilterBar.Event.FilterDidChange, this._filterDidChange, this);
    5657        this._timelineContentBrowser.navigationBar.addNavigationItem(this._filterBarNavigationItem);
    5758        this.addSubview(this._timelineContentBrowser);
     
    8687        WebInspector.ContentView.addEventListener(WebInspector.ContentView.Event.SupplementalRepresentedObjectsDidChange, this._contentViewSupplementalRepresentedObjectsDidChange, this);
    8788
     89        WebInspector.TimelineView.addEventListener(WebInspector.TimelineView.Event.RecordWasFiltered, this._recordWasFiltered, this);
     90
    8891        for (let instrument of this._recording.instruments)
    8992            this._instrumentAdded(instrument);
     
    214217    {
    215218        this._timelineContentBrowser.goForward();
    216     }
    217 
    218     filterDidChange()
    219     {
    220         if (!this.currentTimelineView)
    221             return;
    222 
    223         this.currentTimelineView.filterDidChange();
    224     }
    225 
    226     recordWasFiltered(record, filtered)
    227     {
    228         if (!this.currentTimelineView)
    229             return;
    230 
    231         this._timelineOverview.recordWasFiltered(this.currentTimelineView.representedObject, record, filtered);
    232     }
    233 
    234     matchTreeElementAgainstCustomFilters(treeElement)
    235     {
    236         if (this.currentTimelineView && !this.currentTimelineView.matchTreeElementAgainstCustomFilters(treeElement))
    237             return false;
    238 
    239         let startTime = this._timelineOverview.selectionStartTime;
    240         let endTime = startTime + this._timelineOverview.selectionDuration;
    241         let currentTime = this._currentTime || this._recording.startTime;
    242 
    243         if (this._timelineOverview.viewMode === WebInspector.TimelineOverview.ViewMode.RenderingFrames) {
    244             console.assert(this._renderingFrameTimeline);
    245 
    246             if (this._renderingFrameTimeline && this._renderingFrameTimeline.records.length) {
    247                 let records = this._renderingFrameTimeline.records;
    248                 let startIndex = this._timelineOverview.timelineRuler.snapInterval ? startTime : Math.floor(startTime);
    249                 if (startIndex >= records.length)
    250                     return false;
    251 
    252                 let endIndex = this._timelineOverview.timelineRuler.snapInterval ? endTime - 1: Math.floor(endTime);
    253                 endIndex = Math.min(endIndex, records.length - 1);
    254                 console.assert(startIndex <= endIndex, startIndex);
    255 
    256                 startTime = records[startIndex].startTime;
    257                 endTime = records[endIndex].endTime;
    258             }
    259         }
    260 
    261         function checkTimeBounds(itemStartTime, itemEndTime)
    262         {
    263             itemStartTime = itemStartTime || currentTime;
    264             itemEndTime = itemEndTime || currentTime;
    265 
    266             return startTime <= itemEndTime && itemStartTime <= endTime;
    267         }
    268 
    269         if (treeElement instanceof WebInspector.ResourceTreeElement) {
    270             var resource = treeElement.resource;
    271             return checkTimeBounds(resource.requestSentTimestamp, resource.finishedOrFailedTimestamp);
    272         }
    273 
    274         if (treeElement instanceof WebInspector.SourceCodeTimelineTreeElement) {
    275             var sourceCodeTimeline = treeElement.sourceCodeTimeline;
    276 
    277             // Do a quick check of the timeline bounds before we check each record.
    278             if (!checkTimeBounds(sourceCodeTimeline.startTime, sourceCodeTimeline.endTime))
    279                 return false;
    280 
    281             for (var record of sourceCodeTimeline.records) {
    282                 if (checkTimeBounds(record.startTime, record.endTime))
    283                     return true;
    284             }
    285 
    286             return false;
    287         }
    288 
    289         if (treeElement instanceof WebInspector.ProfileNodeTreeElement) {
    290             var profileNode = treeElement.profileNode;
    291             if (checkTimeBounds(profileNode.startTime, profileNode.endTime))
    292                 return true;
    293 
    294             return false;
    295         }
    296 
    297         if (treeElement instanceof WebInspector.TimelineRecordTreeElement) {
    298             var record = treeElement.record;
    299             return checkTimeBounds(record.startTime, record.endTime);
    300         }
    301 
    302         console.error("Unknown TreeElement, can't filter by time.");
    303         return true;
    304219    }
    305220
     
    470385        if (this._timelineOverview.timelineRuler.entireRangeSelected)
    471386            this._updateTimelineViewSelection(this._overviewTimelineView);
    472 
    473         // Filter records on new recording times.
    474         // FIXME: <https://webkit.org/b/154924> Web Inspector: hook up grid row filtering in the new Timelines UI
    475387
    476388        // Force a layout now since we are already in an animation frame and don't need to delay it until the next.
     
    700612            this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
    701613        }
    702 
    703         // Delay until the next frame to stay in sync with the current timeline view's time-based layout changes.
    704         requestAnimationFrame(function() {
    705             var selectedTreeElement = this.currentTimelineView && this.currentTimelineView.navigationSidebarTreeOutline ? this.currentTimelineView.navigationSidebarTreeOutline.selectedTreeElement : null;
    706             var selectionWasHidden = selectedTreeElement && selectedTreeElement.hidden;
    707 
    708             // Filter records on new timeline selection.
    709             // FIXME: <https://webkit.org/b/154924> Web Inspector: hook up grid row filtering in the new Timelines UI
    710 
    711             if (selectedTreeElement && selectedTreeElement.hidden !== selectionWasHidden)
    712                 this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
    713         }.bind(this));
    714614    }
    715615
     
    797697        this._updateTimelineOverviewHeight();
    798698    }
     699
     700    _filterDidChange()
     701    {
     702        if (!this.currentTimelineView)
     703            return;
     704
     705        this.currentTimelineView.updateFilter(this._filterBarNavigationItem.filterBar.filters);
     706    }
     707
     708    _recordWasFiltered(event)
     709    {
     710        if (event.target !== this.currentTimelineView)
     711            return;
     712
     713        let record = event.data.record;
     714        let filtered = event.data.filtered;
     715        this._timelineOverview.recordWasFiltered(this.currentTimelineView.representedObject, record, filtered);
     716    }
    799717};
  • trunk/Source/WebInspectorUI/UserInterface/Views/TimelineView.js

    r199972 r200067  
    4444    // Public
    4545
     46    get navigationItems()
     47    {
     48        return this._scopeBar ? [this._scopeBar] : [];
     49    }
     50
    4651    get navigationSidebarTreeOutlineScopeBar()
    4752    {
     
    8691        this._startTime = x;
    8792
     93        this._filterTimesDidChange();
    8894        this.needsLayout();
    8995    }
     
    103109        this._endTime = x;
    104110
     111        this._filterTimesDidChange();
    105112        this.needsLayout();
    106113    }
     
    129136        }
    130137
    131         if (checkIfLayoutIsNeeded.call(this, oldCurrentTime) || checkIfLayoutIsNeeded.call(this, this._currentTime))
     138        if (checkIfLayoutIsNeeded.call(this, oldCurrentTime) || checkIfLayoutIsNeeded.call(this, this._currentTime)) {
     139            this._filterTimesDidChange();
    132140            this.needsLayout();
    133     }
    134 
    135     reset()
    136     {
    137         // Implemented by sub-classes if needed.
    138     }
    139 
    140     filterDidChange()
    141     {
    142         // Implemented by sub-classes if needed.
     141        }
     142    }
     143
     144    get filterStartTime()
     145    {
     146        // Implemented by sub-classes if needed.
     147        return this.startTime;
     148    }
     149
     150    get filterEndTime()
     151    {
     152        // Implemented by sub-classes if needed.
     153        return this.endTime;
     154    }
     155
     156    setupDataGrid(dataGrid)
     157    {
     158        console.assert(!this._timelineDataGrid);
     159
     160        this._timelineDataGrid = dataGrid;
     161        this._timelineDataGrid.filterDelegate = this;
     162        this._timelineDataGrid.addEventListener(WebInspector.DataGrid.Event.SelectedNodeChanged, () => {
     163            this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
     164        });
     165
     166        this._timelineDataGrid.addEventListener(WebInspector.DataGrid.Event.NodeWasFiltered, (event) => {
     167            let node = event.data.node;
     168            if (!(node instanceof WebInspector.TimelineDataGridNode))
     169                return;
     170
     171            this.dispatchEventToListeners(WebInspector.TimelineView.Event.RecordWasFiltered, {record: node.record, filtered: node.hidden});
     172        });
     173
     174        this._timelineDataGrid.addEventListener(WebInspector.DataGrid.Event.FilterDidChange, (event) => {
     175            this.filterDidChange();
     176        });
    143177    }
    144178
     
    167201    }
    168202
    169     matchTreeElementAgainstCustomFilters(treeElement)
     203    reset()
     204    {
     205        // Implemented by sub-classes if needed.
     206    }
     207
     208    updateFilter(filters)
     209    {
     210        if (!this._timelineDataGrid)
     211            return;
     212
     213        this._timelineDataGrid.filterText = filters ? filters.text : "";
     214    }
     215
     216    matchDataGridNodeAgainstCustomFilters(node)
    170217    {
    171218        // Implemented by sub-classes if needed.
    172219        return true;
    173     }
    174 
    175     filterUpdated()
    176     {
    177         this.dispatchEventToListeners(WebInspector.ContentView.Event.SelectionPathComponentsDidChange);
    178220    }
    179221
     
    187229    }
    188230
     231    // DataGrid filter delegate
     232
     233    dataGridMatchNodeAgainstCustomFilters(node)
     234    {
     235        console.assert(node);
     236        if (!this.matchDataGridNodeAgainstCustomFilters(node))
     237            return false;
     238
     239        let startTime = this.filterStartTime;
     240        let endTime = this.filterEndTime;
     241        let currentTime = this.currentTime;
     242
     243        function checkTimeBounds(itemStartTime, itemEndTime)
     244        {
     245            itemStartTime = itemStartTime || currentTime;
     246            itemEndTime = itemEndTime || currentTime;
     247
     248            return startTime <= itemEndTime && itemStartTime <= endTime;
     249        }
     250
     251        if (node instanceof WebInspector.ResourceTimelineDataGridNode) {
     252            let resource = node.resource;
     253            return checkTimeBounds(resource.requestSentTimestamp, resource.finishedOrFailedTimestamp);
     254        }
     255
     256        if (node instanceof WebInspector.SourceCodeTimelineTimelineDataGridNode) {
     257            let sourceCodeTimeline = node.sourceCodeTimeline;
     258
     259            // Do a quick check of the timeline bounds before we check each record.
     260            if (!checkTimeBounds(sourceCodeTimeline.startTime, sourceCodeTimeline.endTime))
     261                return false;
     262
     263            for (let record of sourceCodeTimeline.records) {
     264                if (checkTimeBounds(record.startTime, record.endTime))
     265                    return true;
     266            }
     267
     268            return false;
     269        }
     270
     271        if (node instanceof WebInspector.ProfileNodeDataGridNode) {
     272            let profileNode = node.profileNode;
     273            if (checkTimeBounds(profileNode.startTime, profileNode.endTime))
     274                return true;
     275
     276            return false;
     277        }
     278
     279        if (node instanceof WebInspector.TimelineDataGridNode) {
     280            let record = node.record;
     281            return checkTimeBounds(record.startTime, record.endTime);
     282        }
     283
     284        console.error("Unknown DataGridNode, can't filter by time.");
     285        return true;
     286    }
     287
    189288    // Protected
    190289
     
    193292        // Implemented by sub-classes if needed.
    194293    }
     294
     295    filterDidChange()
     296    {
     297        // Implemented by sub-classes if needed.
     298    }
     299
     300    // Private
     301
     302    _filterTimesDidChange()
     303    {
     304        if (!this._timelineDataGrid || this._updateFilterTimeout)
     305            return;
     306
     307        function delayedWork()
     308        {
     309            this._updateFilterTimeout = undefined;
     310            this._timelineDataGrid.filterDidChange();
     311        }
     312
     313        this._updateFilterTimeout = setTimeout(delayedWork.bind(this), 0);
     314    }
    195315};
     316
     317WebInspector.TimelineView.Event = {
     318    RecordWasFiltered: "record-was-filtered"
     319};
Note: See TracChangeset for help on using the changeset viewer.