OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 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'; |
| 29 |
| 30 // Minimum width to size panels to, in pixels. |
| 31 var MIN_PANEL_WIDTH = 50; |
| 32 |
| 33 // We inherit from View. |
| 34 var superClass = View; |
| 35 |
| 36 /** |
| 37 * @constructor |
| 38 */ |
| 39 function ResizableVerticalSplitView(leftView, rightView, sizerView) { |
| 40 // Call superclass's constructor. |
| 41 superClass.call(this); |
| 42 |
| 43 this.leftView_ = leftView; |
| 44 this.rightView_ = rightView; |
| 45 this.sizerView_ = sizerView; |
| 46 |
| 47 this.mouseDragging_ = false; |
| 48 this.touchDragging_ = false; |
| 49 |
| 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)); |
| 57 |
| 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 } |
| 64 |
| 65 ResizableVerticalSplitView.prototype = { |
| 66 // Inherit the superclass's methods. |
| 67 __proto__: superClass.prototype, |
| 68 |
| 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 }, |
| 76 |
| 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); |
| 82 |
| 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)); |
| 86 |
| 87 // Calculate the horizontal split points. |
| 88 var leftboxWidth = this.leftSplit_; |
| 89 var sizerWidth = this.sizerView_.getWidth(); |
| 90 var rightboxWidth = width - (leftboxWidth + sizerWidth); |
| 91 |
| 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 } |
| 97 |
| 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 }, |
| 105 |
| 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 }, |
| 112 |
| 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 }, |
| 121 |
| 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 }, |
| 132 |
| 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 }, |
| 143 |
| 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 }, |
| 152 |
| 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 }, |
| 163 |
| 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 }, |
| 174 |
| 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()); |
| 181 |
| 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); |
| 187 |
| 188 // Force a layout with the new |leftSplit_|. |
| 189 this.setGeometry( |
| 190 this.getLeft(), this.getTop(), this.getWidth(), this.getHeight()); |
| 191 }, |
| 192 }; |
| 193 |
| 194 return ResizableVerticalSplitView; |
| 195 })(); |
| 196 |
OLD | NEW |