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.
6 * This view implements a vertically split display with a draggable divider.
10 * +----------------------++----------------+
15 * | leftView || rightView |
21 * +----------------------++----------------+
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.
27 var ResizableVerticalSplitView
= (function() {
30 // Minimum width to size panels to, in pixels.
31 var MIN_PANEL_WIDTH
= 50;
33 // We inherit from View.
34 var superClass
= View
;
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));
65 ResizableVerticalSplitView
.prototype = {
66 // Inherit the superclass's methods.
67 __proto__
: superClass
.prototype,
70 * Sets the width of the left view.
71 * @param {Integer} px The number of pixels
73 setLeftSplit: function(px
) {
78 * Repositions all of the elements to fit the window.
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%.
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
);
98 // Position the boxes using calculated split points.
99 this.leftView_
.setGeometry(left
, top
, leftboxWidth
, height
);
100 this.sizerView_
.setGeometry(this.leftView_
.getRight(), top
,
102 this.rightView_
.setGeometry(this.sizerView_
.getRight(), top
,
103 rightboxWidth
, height
);
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
);
114 * Called once the sizer is clicked on. Starts moving the sizer in response
115 * to future mouse movement.
117 onMouseDragSizerStart_: function(event
) {
118 this.mouseDragging_
= true;
119 event
.preventDefault();
123 * Called when the mouse has moved.
125 onMouseDragSizer_: function(event
) {
126 if (!this.mouseDragging_
)
128 // If dragging has started, move the sizer.
129 this.onDragSizer_(event
.pageX
);
130 event
.preventDefault();
134 * Called once the mouse has been released.
136 onMouseDragSizerEnd_: function(event
) {
137 if (!this.mouseDragging_
)
140 this.mouseDragging_
= false;
141 event
.preventDefault();
145 * Called when the user touches the sizer. Starts moving the sizer in
146 * response to future touch events.
148 onTouchDragSizerStart_: function(event
) {
149 this.touchDragging_
= true;
150 event
.preventDefault();
154 * Called when the mouse has moved after dragging started.
156 onTouchDragSizer_: function(event
) {
157 if (!this.touchDragging_
)
159 // If dragging has started, move the sizer.
160 this.onDragSizer_(event
.touches
[0].pageX
);
161 event
.preventDefault();
165 * Called once the user stops touching the screen.
167 onTouchDragSizerEnd_: function(event
) {
168 if (!this.touchDragging_
)
171 this.touchDragging_
= false;
172 event
.preventDefault();
176 * Common code used for both mouse and touch dragging.
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_|.
190 this.getLeft(), this.getTop(), this.getWidth(), this.getHeight());
194 return ResizableVerticalSplitView
;