Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / resources / net_internals / resizable_vertical_split_view.js
blob644ae9b8206a6f4858be7a855e29bec091bbdc66
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 /**
6  * This view implements a vertically split display with a draggable divider.
7  *
8  *                  <<-- sizer -->>
9  *
10  *  +----------------------++----------------+
11  *  |                      ||                |
12  *  |                      ||                |
13  *  |                      ||                |
14  *  |                      ||                |
15  *  |       leftView       ||   rightView    |
16  *  |                      ||                |
17  *  |                      ||                |
18  *  |                      ||                |
19  *  |                      ||                |
20  *  |                      ||                |
21  *  +----------------------++----------------+
22  *
23  * @param {!View} leftView The widget to position on the left.
24  * @param {!View} rightView The widget to position on the right.
25  * @param {!DivView} sizerView The widget that will serve as draggable divider.
26  */
27 var ResizableVerticalSplitView = (function() {
28   'use strict';
30   // Minimum width to size panels to, in pixels.
31   var MIN_PANEL_WIDTH = 50;
33   // We inherit from View.
34   var superClass = View;
36   /**
37    * @constructor
38    */
39   function ResizableVerticalSplitView(leftView, rightView, sizerView) {
40     // Call superclass's constructor.
41     superClass.call(this);
43     this.leftView_ = leftView;
44     this.rightView_ = rightView;
45     this.sizerView_ = sizerView;
47     this.mouseDragging_ = false;
48     this.touchDragging_ = false;
50     // Setup the "sizer" so it can be dragged left/right to reposition the
51     // vertical split.  The start event must occur within the sizer's node,
52     // but subsequent events may occur anywhere.
53     var node = sizerView.getNode();
54     node.addEventListener('mousedown', this.onMouseDragSizerStart_.bind(this));
55     window.addEventListener('mousemove', this.onMouseDragSizer_.bind(this));
56     window.addEventListener('mouseup', this.onMouseDragSizerEnd_.bind(this));
58     node.addEventListener('touchstart', this.onTouchDragSizerStart_.bind(this));
59     window.addEventListener('touchmove', this.onTouchDragSizer_.bind(this));
60     window.addEventListener('touchend', this.onTouchDragSizerEnd_.bind(this));
61     window.addEventListener('touchcancel',
62                             this.onTouchDragSizerEnd_.bind(this));
63   }
65   ResizableVerticalSplitView.prototype = {
66     // Inherit the superclass's methods.
67     __proto__: superClass.prototype,
69     /**
70      * Sets the width of the left view.
71      * @param {Integer} px The number of pixels
72      */
73     setLeftSplit: function(px) {
74       this.leftSplit_ = px;
75     },
77     /**
78      * Repositions all of the elements to fit the window.
79      */
80     setGeometry: function(left, top, width, height) {
81       superClass.prototype.setGeometry.call(this, left, top, width, height);
83       // If this is the first setGeometry(), initialize the split point at 50%.
84       if (!this.leftSplit_)
85         this.leftSplit_ = parseInt((width / 2).toFixed(0));
87       // Calculate the horizontal split points.
88       var leftboxWidth = this.leftSplit_;
89       var sizerWidth = this.sizerView_.getWidth();
90       var rightboxWidth = width - (leftboxWidth + sizerWidth);
92       // Don't let the right pane get too small.
93       if (rightboxWidth < MIN_PANEL_WIDTH) {
94         rightboxWidth = MIN_PANEL_WIDTH;
95         leftboxWidth = width - (sizerWidth + rightboxWidth);
96       }
98       // Position the boxes using calculated split points.
99       this.leftView_.setGeometry(left, top, leftboxWidth, height);
100       this.sizerView_.setGeometry(this.leftView_.getRight(), top,
101                                   sizerWidth, height);
102       this.rightView_.setGeometry(this.sizerView_.getRight(), top,
103                                   rightboxWidth, height);
104     },
106     show: function(isVisible) {
107       superClass.prototype.show.call(this, isVisible);
108       this.leftView_.show(isVisible);
109       this.sizerView_.show(isVisible);
110       this.rightView_.show(isVisible);
111     },
113     /**
114      * Called once the sizer is clicked on. Starts moving the sizer in response
115      * to future mouse movement.
116      */
117     onMouseDragSizerStart_: function(event) {
118       this.mouseDragging_ = true;
119       event.preventDefault();
120     },
122     /**
123      * Called when the mouse has moved.
124      */
125     onMouseDragSizer_: function(event) {
126       if (!this.mouseDragging_)
127         return;
128       // If dragging has started, move the sizer.
129       this.onDragSizer_(event.pageX);
130       event.preventDefault();
131     },
133     /**
134      * Called once the mouse has been released.
135      */
136     onMouseDragSizerEnd_: function(event) {
137       if (!this.mouseDragging_)
138         return;
139       // Dragging is over.
140       this.mouseDragging_ = false;
141       event.preventDefault();
142     },
144     /**
145      * Called when the user touches the sizer.  Starts moving the sizer in
146      * response to future touch events.
147      */
148     onTouchDragSizerStart_: function(event) {
149       this.touchDragging_ = true;
150       event.preventDefault();
151     },
153     /**
154      * Called when the mouse has moved after dragging started.
155      */
156     onTouchDragSizer_: function(event) {
157       if (!this.touchDragging_)
158         return;
159       // If dragging has started, move the sizer.
160       this.onDragSizer_(event.touches[0].pageX);
161       event.preventDefault();
162     },
164     /**
165      * Called once the user stops touching the screen.
166      */
167     onTouchDragSizerEnd_: function(event) {
168       if (!this.touchDragging_)
169         return;
170       // Dragging is over.
171       this.touchDragging_ = false;
172       event.preventDefault();
173     },
175     /**
176      * Common code used for both mouse and touch dragging.
177      */
178     onDragSizer_: function(pageX) {
179       // Convert from page coordinates, to view coordinates.
180       this.leftSplit_ = (pageX - this.getLeft());
182       // Avoid shrinking the left box too much.
183       this.leftSplit_ = Math.max(this.leftSplit_, MIN_PANEL_WIDTH);
184       // Avoid shrinking the right box too much.
185       this.leftSplit_ = Math.min(
186           this.leftSplit_, this.getWidth() - MIN_PANEL_WIDTH);
188       // Force a layout with the new |leftSplit_|.
189       this.setGeometry(
190           this.getLeft(), this.getTop(), this.getWidth(), this.getHeight());
191     },
192   };
194   return ResizableVerticalSplitView;
195 })();