Web Inspector: unify resizer implementations used by DataGrid and Sidebar
authorburg@cs.washington.edu <burg@cs.washington.edu@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Mar 2015 20:41:47 +0000 (20:41 +0000)
committerburg@cs.washington.edu <burg@cs.washington.edu@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Tue, 24 Mar 2015 20:41:47 +0000 (20:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=142407

Reviewed by Timothy Hatcher.

Both of these implementations do the same thing slightly differently. Unify the code
and use the "glass pane" technique to preserve cursor while dragging over links or text.

This patch implements vertical and horizontal rule orientations. Further refactorings
to use this class may need to add "Indeterminate" orientation to support moving the inspector
window by its fake toolbar element.

* UserInterface/Main.html:
* UserInterface/Views/DataGrid.css:
(.data-grid .resizer):
(.data-grid-resizer): Deleted.
* UserInterface/Views/DataGrid.js: Store Resizer instances rather than resizer elements.
Use symbols to secretly store neighbor column ids on the resizer objects. Stop using
WebInspector.elementDragStart, as I would like to deprecate it in favor of Resizer instances.

(WebInspector.DataGrid):
(WebInspector.DataGrid.prototype._positionResizerElements):
(WebInspector.DataGrid.prototype.resizerDragStarted):
(WebInspector.DataGrid.prototype.resizerDragging):
(WebInspector.DataGrid.prototype.resizerDragEnded):
(WebInspector.DataGrid.prototype._startResizerDragging): Deleted.
(WebInspector.DataGrid.prototype._resizerDragging): Deleted.
(WebInspector.DataGrid.prototype._endResizerDragging): Deleted.
* UserInterface/Views/Resizer.css:
(.resizer):
(.resizer.vertical-rule):
(.resizer.horizontal-rule):
(.glass-pane-for-drag):
* UserInterface/Views/Resizer.js: Added.
(WebInspector.Resizer):
(WebInspector.Resizer.prototype.get element):
(WebInspector.Resizer.prototype.get orientation):
(WebInspector.Resizer.prototype.get initialPosition):
(WebInspector.Resizer.prototype._currentPosition):
(WebInspector.Resizer.prototype._resizerMouseDown):
(WebInspector.Resizer.prototype._resizerMouseMoved):
(WebInspector.Resizer.prototype._resizerMouseUp):
* UserInterface/Views/Sidebar.css:
(.sidebar > .resizer): Deleted.
* UserInterface/Views/Sidebar.js:
(WebInspector.Sidebar):
(WebInspector.Sidebar.prototype.resizerDragStarted):
(WebInspector.Sidebar.prototype.resizerDragging):
(WebInspector.Sidebar.prototype.resizerDragEnded):
(WebInspector.Sidebar.prototype._navigationItemSelected):
(WebInspector.Sidebar.prototype._resizerMouseDown): Deleted.
(WebInspector.Sidebar.prototype._resizerMouseMoved): Deleted.
(WebInspector.Sidebar.prototype._resizerMouseUp): Deleted.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@181903 268f45cc-cd09-0410-ab3c-d52691b4dbfc

Source/WebInspectorUI/ChangeLog
Source/WebInspectorUI/UserInterface/Main.html
Source/WebInspectorUI/UserInterface/Views/DataGrid.css
Source/WebInspectorUI/UserInterface/Views/DataGrid.js
Source/WebInspectorUI/UserInterface/Views/Resizer.css [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Views/Resizer.js [new file with mode: 0644]
Source/WebInspectorUI/UserInterface/Views/Sidebar.css
Source/WebInspectorUI/UserInterface/Views/Sidebar.js

index 3e17093..603e77a 100644 (file)
@@ -1,3 +1,59 @@
+2015-03-06  Brian J. Burg  <burg@cs.washington.edu>
+
+        Web Inspector: unify resizer implementations used by DataGrid and Sidebar
+        https://bugs.webkit.org/show_bug.cgi?id=142407
+
+        Reviewed by Timothy Hatcher.
+
+        Both of these implementations do the same thing slightly differently. Unify the code
+        and use the "glass pane" technique to preserve cursor while dragging over links or text.
+
+        This patch implements vertical and horizontal rule orientations. Further refactorings
+        to use this class may need to add "Indeterminate" orientation to support moving the inspector
+        window by its fake toolbar element.
+
+        * UserInterface/Main.html:
+        * UserInterface/Views/DataGrid.css:
+        (.data-grid .resizer):
+        (.data-grid-resizer): Deleted.
+        * UserInterface/Views/DataGrid.js: Store Resizer instances rather than resizer elements.
+        Use symbols to secretly store neighbor column ids on the resizer objects. Stop using
+        WebInspector.elementDragStart, as I would like to deprecate it in favor of Resizer instances.
+
+        (WebInspector.DataGrid):
+        (WebInspector.DataGrid.prototype._positionResizerElements):
+        (WebInspector.DataGrid.prototype.resizerDragStarted):
+        (WebInspector.DataGrid.prototype.resizerDragging):
+        (WebInspector.DataGrid.prototype.resizerDragEnded):
+        (WebInspector.DataGrid.prototype._startResizerDragging): Deleted.
+        (WebInspector.DataGrid.prototype._resizerDragging): Deleted.
+        (WebInspector.DataGrid.prototype._endResizerDragging): Deleted.
+        * UserInterface/Views/Resizer.css:
+        (.resizer):
+        (.resizer.vertical-rule):
+        (.resizer.horizontal-rule):
+        (.glass-pane-for-drag):
+        * UserInterface/Views/Resizer.js: Added.
+        (WebInspector.Resizer):
+        (WebInspector.Resizer.prototype.get element):
+        (WebInspector.Resizer.prototype.get orientation):
+        (WebInspector.Resizer.prototype.get initialPosition):
+        (WebInspector.Resizer.prototype._currentPosition):
+        (WebInspector.Resizer.prototype._resizerMouseDown):
+        (WebInspector.Resizer.prototype._resizerMouseMoved):
+        (WebInspector.Resizer.prototype._resizerMouseUp):
+        * UserInterface/Views/Sidebar.css:
+        (.sidebar > .resizer): Deleted.
+        * UserInterface/Views/Sidebar.js:
+        (WebInspector.Sidebar):
+        (WebInspector.Sidebar.prototype.resizerDragStarted):
+        (WebInspector.Sidebar.prototype.resizerDragging):
+        (WebInspector.Sidebar.prototype.resizerDragEnded):
+        (WebInspector.Sidebar.prototype._navigationItemSelected):
+        (WebInspector.Sidebar.prototype._resizerMouseDown): Deleted.
+        (WebInspector.Sidebar.prototype._resizerMouseMoved): Deleted.
+        (WebInspector.Sidebar.prototype._resizerMouseUp): Deleted.
+
 2015-03-17  Jono Wells  <jonowells@apple.com>
 
         Web Inspector: Debugger sidebar should have a filter button for breakpoints
index 180dac2..028467f 100644 (file)
     <link rel="stylesheet" href="Views/QuickConsole.css">
     <link rel="stylesheet" href="Views/RadioButtonNavigationItem.css">
     <link rel="stylesheet" href="Views/ReplayDashboardView.css">
+    <link rel="stylesheet" href="Views/Resizer.css">
     <link rel="stylesheet" href="Views/ResourceIcons.css">
     <link rel="stylesheet" href="Views/ResourceSidebarPanel.css">
     <link rel="stylesheet" href="Views/ResourceTreeElement.css">
     <script src="Views/QuickConsoleNavigationBar.js"></script>
     <script src="Views/RadioButtonNavigationItem.js"></script>
     <script src="Views/ReplayDashboardView.js"></script>
+    <script src="Views/Resizer.js"></script>
     <script src="Views/ResourceClusterContentView.js"></script>
     <script src="Views/ResourceDetailsSidebarPanel.js"></script>
     <script src="Views/ResourceSidebarPanel.js"></script>
index 416484c..79ab83c 100644 (file)
@@ -302,11 +302,6 @@ body.mac-platform.legacy .data-grid:focus tr.selected {
     display: block;
 }
 
-.data-grid-resizer {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    width: 5px;
+.data-grid .resizer {
     z-index: 500;
-    cursor: col-resize;
 }
index 6235c9f..e52d87c 100644 (file)
@@ -41,7 +41,7 @@ WebInspector.DataGrid = function(columnsData, editCallback, deleteCallback, pref
     this.selected = false;
     this.dataGrid = this;
     this.indentWidth = 15;
-    this.resizerElements = [];
+    this.resizers = [];
     this._columnWidthsInitialized = false;
 
     this.element = document.createElement("div");
@@ -112,6 +112,9 @@ WebInspector.DataGrid.SortOrder = {
     Descending: "data-grid-sort-order-descending"
 };
 
+WebInspector.DataGrid.PreviousColumnOrdinalSymbol = Symbol("previous-column-ordinal");
+WebInspector.DataGrid.NextColumnOrdinalSymbol = Symbol("next-column-ordinal");
+
 WebInspector.DataGrid.SortColumnAscendingStyleClassName = "sort-ascending";
 WebInspector.DataGrid.SortColumnDescendingStyleClassName = "sort-descending";
 WebInspector.DataGrid.SortableColumnStyleClassName = "sortable";
@@ -662,43 +665,40 @@ WebInspector.DataGrid.prototype = {
     _positionResizerElements: function()
     {
         var left = 0;
-        var previousResizerElement = null;
+        var previousResizer = null;
 
         // Make n - 1 resizers for n columns.
         for (var i = 0; i < this.orderedColumns.length - 1; ++i) {
-            var resizerElement = this.resizerElements[i];
-
-            if (!resizerElement) {
-                // This is the first call to updateWidth, so the resizers need
-                // to be created.
-                resizerElement = document.createElement("div");
-                resizerElement.classList.add("data-grid-resizer");
+            // Create a new resizer if one does not exist for this column.
+            if (i === this.resizers.length) {
+                resizer = new WebInspector.Resizer(WebInspector.Resizer.RuleOrientation.Vertical, this);
+                this.resizers[i] = resizer;
                 // This resizer is associated with the column to its right.
-                resizerElement.addEventListener("mousedown", this._startResizerDragging.bind(this), false);
-                this.element.appendChild(resizerElement);
-                this.resizerElements[i] = resizerElement;
+                this.element.appendChild(resizer.element);
             }
 
+            var resizer = this.resizers[i];
+
             // Get the width of the cell in the first (and only) row of the
             // header table in order to determine the width of the column, since
             // it is not possible to query a column for its width.
             left += this._headerTableBodyElement.rows[0].cells[i].offsetWidth;
 
             if (this._isColumnVisible(this.orderedColumns[i])) {
-                resizerElement.style.removeProperty("display");
-                resizerElement.style.left = left + "px";
-                resizerElement.leftNeighboringColumnID = i;
-                if (previousResizerElement)
-                    previousResizerElement.rightNeighboringColumnID = i;
-                previousResizerElement = resizerElement;
+                resizer.element.style.removeProperty("display");
+                resizer.element.style.left = left + "px";
+                resizer[WebInspector.DataGrid.PreviousColumnOrdinalSymbol] = i;
+                if (previousResizer)
+                    previousResizer[WebInspector.DataGrid.NextColumnOrdinalSymbol] = i;
+                previousResizer = resizer;
             } else {
-                resizerElement.style.setProperty("display", "none");
-                resizerElement.leftNeighboringColumnID = 0;
-                resizerElement.rightNeighboringColumnID = 0;
+                resizer.element.style.setProperty("display", "none");
+                resizer[WebInspector.DataGrid.PreviousColumnOrdinalSymbol] = 0;
+                resizer[WebInspector.DataGrid.NextColumnOrdinalSymbol] = 0;
             }
         }
-        if (previousResizerElement)
-            previousResizerElement.rightNeighboringColumnID = this.orderedColumns.length - 1;
+        if (previousResizer)
+            previousResizer[WebInspector.DataGrid.NextColumnOrdinalSymbol] = this.orderedColumns.length - 1;
     },
 
     addPlaceholderNode: function()
@@ -1242,35 +1242,27 @@ WebInspector.DataGrid.prototype = {
         this._resizeMethod = method;
     },
 
-    _startResizerDragging: function(event)
+    resizerDragStarted: function(resizer)
     {
-        if (event.button !== 0 || event.ctrlKey)
-            return;
+        if (!resizer[WebInspector.DataGrid.NextColumnOrdinalSymbol])
+            return true; // Abort the drag;
 
-        this._currentResizer = event.target;
-        if (!this._currentResizer.rightNeighboringColumnID)
-            return;
-
-        WebInspector.elementDragStart(this._currentResizer, this._resizerDragging.bind(this),
-            this._endResizerDragging.bind(this), event, "col-resize");
+        this._currentResizer = resizer;
     },
 
-    _resizerDragging: function(event)
+    resizerDragging: function(resizer, positionDelta)
     {
-        if (event.button !== 0)
-            return;
-
-        var resizer = this._currentResizer;
-        if (!resizer)
+        console.assert(resizer === this._currentResizer, resizer, this._currentResizer);
+        if (resizer != this._currentResizer)
             return;
 
         // Constrain the dragpoint to be within the containing div of the
         // datagrid.
-        var dragPoint = event.clientX - this.element.totalOffsetLeft;
+        var dragPoint = (resizer.initialPosition - positionDelta) - this.element.totalOffsetLeft;
         // Constrain the dragpoint to be within the space made up by the
         // column directly to the left and the column directly to the right.
-        var leftCellIndex = resizer.leftNeighboringColumnID;
-        var rightCellIndex = resizer.rightNeighboringColumnID;
+        var leftCellIndex = resizer[WebInspector.DataGrid.PreviousColumnOrdinalSymbol];
+        var rightCellIndex = resizer[WebInspector.DataGrid.NextColumnOrdinalSymbol];
         var firstRowCells = this._headerTableBodyElement.rows[0].cells;
         var leftEdgeOfPreviousColumn = 0;
         for (var i = 0; i < leftCellIndex; i++)
@@ -1278,7 +1270,7 @@ WebInspector.DataGrid.prototype = {
 
         // Differences for other resize methods
         if (this.resizeMethod === WebInspector.DataGrid.ResizeMethod.Last) {
-            rightCellIndex = this.resizerElements.length;
+            rightCellIndex = this.resizers.length;
         } else if (this.resizeMethod === WebInspector.DataGrid.ResizeMethod.First) {
             leftEdgeOfPreviousColumn += firstRowCells[leftCellIndex].offsetWidth - firstRowCells[0].offsetWidth;
             leftCellIndex = 0;
@@ -1292,7 +1284,7 @@ WebInspector.DataGrid.prototype = {
 
         dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum);
 
-        resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px";
+        resizer.element.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px";
 
         var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTableElement.offsetWidth) * 100) + "%";
         this._headerTableColumnGroupElement.children[leftCellIndex].style.width = percentLeftColumn;
@@ -1307,12 +1299,12 @@ WebInspector.DataGrid.prototype = {
         this.dispatchEventToListeners(WebInspector.DataGrid.Event.DidLayout);
     },
 
-    _endResizerDragging: function(event)
+    resizerDragEnded: function(resizer)
     {
-        if (event.button !== 0)
+        console.assert(resizer === this._currentResizer, resizer, this._currentResizer);
+        if (resizer != this._currentResizer)
             return;
 
-        WebInspector.elementDragEnd(event);
         this._currentResizer = null;
         this.dispatchEventToListeners(WebInspector.DataGrid.Event.DidLayout);
     },
diff --git a/Source/WebInspectorUI/UserInterface/Views/Resizer.css b/Source/WebInspectorUI/UserInterface/Views/Resizer.css
new file mode 100644 (file)
index 0000000..8b33fd3
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 University of Washington.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+.resizer {
+    position: absolute;
+    z-index: 1000;
+}
+
+.resizer.vertical-rule {
+    top: 0;
+    bottom: 0;
+    width: 5px;
+
+    cursor: col-resize;
+}
+
+.resizer.horizontal-rule {
+    left: 0;
+    right: 0;
+    height: 5px;
+
+    cursor: row-resize;
+}
+
+.glass-pane-for-drag {
+    position: absolute;
+    top: 0;
+    bottom: 0;
+    left: 0;
+    right: 0;
+
+    opacity: 0;
+    z-index: 1;
+}
diff --git a/Source/WebInspectorUI/UserInterface/Views/Resizer.js b/Source/WebInspectorUI/UserInterface/Views/Resizer.js
new file mode 100644 (file)
index 0000000..7126119
--- /dev/null
@@ -0,0 +1,164 @@
+/*
+ * Copyright (C) 2015 University of Washington.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+WebInspector.Resizer = function(ruleOrientation, delegate) {
+    // FIXME: Convert this to a WebInspector.Object subclass, and call super().
+    // WebInspector.Object.call(this);
+
+    console.assert(delegate);
+
+    this._delegate = delegate;
+    this._orientation = ruleOrientation;
+    this._element = document.createElement("div");
+    this._element.classList.add(WebInspector.Resizer.StyleClassName);
+
+    if (this._orientation === WebInspector.Resizer.RuleOrientation.Horizontal)
+        this._element.classList.add(WebInspector.Resizer.HorizontalRuleStyleClassName);
+    else if (this._orientation === WebInspector.Resizer.RuleOrientation.Vertical)
+        this._element.classList.add(WebInspector.Resizer.VerticalRuleStyleClassName);
+
+    this._element.addEventListener("mousedown", this._resizerMouseDown.bind(this), false);
+    this._resizerMouseMovedEventListener = this._resizerMouseMoved.bind(this);
+    this._resizerMouseUpEventListener = this._resizerMouseUp.bind(this);
+};
+
+WebInspector.Resizer.RuleOrientation = {
+    Horizontal: Symbol("resizer-rule-orientation-horizontal"),
+    Vertical: Symbol("resizer-rule-orientation-vertical"),
+};
+
+WebInspector.Resizer.StyleClassName = "resizer";
+WebInspector.Resizer.HorizontalRuleStyleClassName = "horizontal-rule";
+WebInspector.Resizer.VerticalRuleStyleClassName = "vertical-rule";
+WebInspector.Resizer.GlassPaneStyleClassName = "glass-pane-for-drag";
+
+WebInspector.Resizer.prototype = {
+    constructor: WebInspector.Resizer,
+    __proto__: WebInspector.Object.prototype,
+
+    // Public
+
+    get element()
+    {
+        return this._element;
+    },
+
+    get orientation()
+    {
+        return this._orientation;
+    },
+
+    get initialPosition()
+    {
+        return this._resizerMouseDownPosition || NaN;
+    },
+
+    // Private
+
+    _currentPosition: function()
+    {
+        if (this._orientation === WebInspector.Resizer.RuleOrientation.Vertical)
+            return event.pageX;
+        if (this._orientation === WebInspector.Resizer.RuleOrientation.Horizontal)
+            return event.pageY;
+
+        console.assert(false, "Should not be reached!");
+    },
+
+    _resizerMouseDown: function(event)
+    {
+        if (event.button !== 0 || event.ctrlKey)
+            return;
+
+        this._resizerMouseDownPosition = this._currentPosition();
+
+        var delegateRequestedAbort = false;
+        if (typeof this._delegate.resizerDragStarted === "function")
+            delegateRequestedAbort = this._delegate.resizerDragStarted(this, event.target);
+
+        if (delegateRequestedAbort) {
+            delete this._resizerMouseDownPosition;
+            return;
+        }
+
+        if (this._orientation === WebInspector.Resizer.RuleOrientation.Vertical)
+            document.body.style.cursor = "col-resize";
+        else {
+            console.assert(this._orientation === WebInspector.Resizer.RuleOrientation.Horizontal);
+            document.body.style.cursor = "row-resize";
+        }
+
+        // Register these listeners on the document so we can track the mouse if it leaves the resizer.
+        document.addEventListener("mousemove", this._resizerMouseMovedEventListener, false);
+        document.addEventListener("mouseup", this._resizerMouseUpEventListener, false);
+
+        event.preventDefault();
+        event.stopPropagation();
+
+        // Install a global "glass pane" which prevents cursor from changing during the drag interaction.
+        // The cursor could change when hovering over links, text, or other elements with cursor cues.
+        // FIXME: when Pointer Events support is available this could be implemented by drawing the cursor ourselves.
+        if (WebInspector._elementDraggingGlassPane)
+            WebInspector._elementDraggingGlassPane.parentElement.removeChild(WebInspector._elementDraggingGlassPane);
+
+        var glassPaneElement = document.createElement("div");
+        glassPaneElement.className = WebInspector.Resizer.GlassPaneStyleClassName;
+        document.body.appendChild(glassPaneElement);
+        WebInspector._elementDraggingGlassPane = glassPaneElement;
+    },
+
+    _resizerMouseMoved: function(event)
+    {
+        event.preventDefault();
+        event.stopPropagation();
+
+        if (typeof this._delegate.resizerDragging === "function")
+            this._delegate.resizerDragging(this, this._resizerMouseDownPosition - this._currentPosition());
+    },
+
+    _resizerMouseUp: function(event)
+    {
+        if (event.button !== 0 || event.ctrlKey)
+            return;
+
+        document.body.style.removeProperty("cursor");
+
+        if (WebInspector._elementDraggingGlassPane) {
+            WebInspector._elementDraggingGlassPane.parentElement.removeChild(WebInspector._elementDraggingGlassPane);
+            delete WebInspector._elementDraggingGlassPane;
+        }
+
+        document.removeEventListener("mousemove", this._resizerMouseMovedEventListener, false);
+        document.removeEventListener("mouseup", this._resizerMouseUpEventListener, false);
+
+        event.preventDefault();
+        event.stopPropagation();
+
+        if (typeof this._delegate.resizerDragEnded === "function")
+            this._delegate.resizerDragEnded(this);
+
+        delete this._resizerMouseDownPosition;
+    }
+};
index dccb566..05e0d75 100644 (file)
@@ -60,17 +60,6 @@ body.mac-platform.legacy.window-inactive .sidebar {
     display: block;
 }
 
-.sidebar > .resizer {
-    position: absolute;
-    top: 0;
-    bottom: 0;
-    width: 5px;
-
-    z-index: 100;
-
-    cursor: col-resize;
-}
-
 .sidebar.right > .resizer {
     left: -3px;
 }
index f675776..b82bc7c 100644 (file)
@@ -39,10 +39,8 @@ WebInspector.Sidebar = function(element, side, sidebarPanels, role, label) {
     if (label)
         this._element.setAttribute("aria-label", label);
 
-    this._resizeElement = document.createElement("div");
-    this._resizeElement.classList.add(WebInspector.Sidebar.ResizeElementStyleClassName);
-    this._resizeElement.addEventListener("mousedown", this._resizerMouseDown.bind(this), false);
-    this._element.insertBefore(this._resizeElement, this._element.firstChild);
+    this._resizer = new WebInspector.Resizer(WebInspector.Resizer.RuleOrientation.Vertical, this);
+    this._element.insertBefore(this._resizer.element, this._element.firstChild);
 
     this._sidebarPanels = [];
 
@@ -57,7 +55,6 @@ WebInspector.Object.deprecatedAddConstructorFunctions(WebInspector.Sidebar);
 
 WebInspector.Sidebar.StyleClassName = "sidebar";
 WebInspector.Sidebar.CollapsedStyleClassName = "collapsed";
-WebInspector.Sidebar.ResizeElementStyleClassName = "resizer";
 WebInspector.Sidebar.AbsoluteMinimumWidth = 200;
 
 WebInspector.Sidebar.Sides = {};
@@ -252,64 +249,33 @@ WebInspector.Sidebar.prototype = {
         return sidebarPanel;
     },
 
-    // Private
-
-    _navigationItemSelected: function(event)
-    {
-        this.selectedSidebarPanel = event.target.selectedNavigationItem ? event.target.selectedNavigationItem.identifier : null;
-    },
+    // Protected
 
-    _resizerMouseDown: function(event)
+    resizerDragStarted: function(resizer)
     {
-        if (event.button !== 0 || event.ctrlKey)
-            return;
-
-        document.body.style.cursor = "col-resize";
-
-        this._resizerMouseMovedEventListener = this._resizerMouseMoved.bind(this);
-        this._resizerMouseUpEventListener = this._resizerMouseUp.bind(this);
-
         this._widthBeforeResize = this.width;
-        this._resizerMouseDownX = event.pageX;
-
-        // Register these listeners on the document so we can track the mouse if it leaves the resizer.
-        document.addEventListener("mousemove", this._resizerMouseMovedEventListener, false);
-        document.addEventListener("mouseup", this._resizerMouseUpEventListener, false);
-
-        event.preventDefault();
-        event.stopPropagation();
     },
 
-    _resizerMouseMoved: function(event)
+    resizerDragging: function(resizer, positionDelta)
     {
-        var deltaX = this._resizerMouseDownX - event.pageX;
-
         if (this._side === WebInspector.Sidebar.Sides.Left)
-            deltaX *= -1;
+            positionDelta *= -1;
 
-        var newWidth = deltaX + this._widthBeforeResize;
+        var newWidth = positionDelta + this._widthBeforeResize;
         this.width = newWidth;
         this.collapsed = (newWidth < (this.minimumWidth / 2));
-
-        event.preventDefault();
-        event.stopPropagation();
     },
 
-    _resizerMouseUp: function(event)
+    resizerDragEnded: function(resizer)
     {
-        if (event.button !== 0 || event.ctrlKey)
-            return;
-
-        document.body.style.removeProperty("cursor");
-
-        document.removeEventListener("mousemove", this._resizerMouseMovedEventListener, false);
-        document.removeEventListener("mouseup", this._resizerMouseUpEventListener, false);
+        delete this._widthBeforeResize;
+    },
 
-        delete this._resizerMouseMovedEventListener;
-        delete this._resizerMouseUpEventListener;
+    // Private
 
-        event.preventDefault();
-        event.stopPropagation();
+    _navigationItemSelected: function(event)
+    {
+        this.selectedSidebarPanel = event.target.selectedNavigationItem ? event.target.selectedNavigationItem.identifier : null;
     }
 };