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;