1// Copyright (c) 2010 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 * @constructor 27 */ 28function ResizableVerticalSplitView(leftView, rightView, sizerView) { 29 View.call(this); 30 31 this.leftView_ = leftView; 32 this.rightView_ = rightView; 33 this.sizerView_ = sizerView; 34 35 // Setup the "sizer" so it can be dragged left/right to reposition the 36 // vertical split. 37 sizerView.getNode().addEventListener( 38 'mousedown', this.onDragSizerStart_.bind(this), true); 39} 40 41inherits(ResizableVerticalSplitView, View); 42 43// Minimum width to size panels to, in pixels. 44ResizableVerticalSplitView.MIN_PANEL_WIDTH = 50; 45 46/** 47 * Repositions all of the elements to fit the window. 48 */ 49ResizableVerticalSplitView.prototype.setGeometry = function( 50 left, top, width, height) { 51 ResizableVerticalSplitView.superClass_.setGeometry.call( 52 this, left, top, width, height); 53 54 // If this is the first setGeometry(), initialize the split point at 50%. 55 if (!this.leftSplit_) 56 this.leftSplit_ = parseInt((width / 2).toFixed(0)); 57 58 // Calculate the horizontal split points. 59 var leftboxWidth = this.leftSplit_; 60 var sizerWidth = this.sizerView_.getWidth(); 61 var rightboxWidth = width - (leftboxWidth + sizerWidth); 62 63 // Don't let the right pane get too small. 64 if (rightboxWidth < ResizableVerticalSplitView.MIN_PANEL_WIDTH) { 65 rightboxWidth = ResizableVerticalSplitView.MIN_PANEL_WIDTH; 66 leftboxWidth = width - (sizerWidth + rightboxWidth); 67 } 68 69 // Position the boxes using calculated split points. 70 this.leftView_.setGeometry(left, top, leftboxWidth, height); 71 this.sizerView_.setGeometry(this.leftView_.getRight(), top, 72 sizerWidth, height); 73 this.rightView_.setGeometry(this.sizerView_.getRight(), top, 74 rightboxWidth, height); 75}; 76 77ResizableVerticalSplitView.prototype.show = function(isVisible) { 78 ResizableVerticalSplitView.superClass_.show.call(this, isVisible); 79 this.leftView_.show(isVisible); 80 this.sizerView_.show(isVisible); 81 this.rightView_.show(isVisible); 82}; 83 84/** 85 * Called once we have clicked into the sizer. Starts capturing the mouse 86 * position to implement dragging. 87 */ 88ResizableVerticalSplitView.prototype.onDragSizerStart_ = function(event) { 89 this.sizerMouseMoveListener_ = this.onDragSizer.bind(this); 90 this.sizerMouseUpListener_ = this.onDragSizerEnd.bind(this); 91 92 window.addEventListener('mousemove', this.sizerMouseMoveListener_, true); 93 window.addEventListener('mouseup', this.sizerMouseUpListener_, true); 94 95 event.preventDefault(); 96}; 97 98/** 99 * Called when the mouse has moved after dragging started. 100 */ 101ResizableVerticalSplitView.prototype.onDragSizer = function(event) { 102 // Convert from page coordinates, to view coordinates. 103 this.leftSplit_ = (event.pageX - this.getLeft()); 104 105 // Avoid shrinking the left box too much. 106 this.leftSplit_ = Math.max( 107 this.leftSplit_, ResizableVerticalSplitView.MIN_PANEL_WIDTH); 108 // Avoid shrinking the right box too much. 109 this.leftSplit_ = Math.min( 110 this.leftSplit_, 111 this.getWidth() - ResizableVerticalSplitView.MIN_PANEL_WIDTH); 112 113 // Force a layout with the new |leftSplit_|. 114 this.setGeometry( 115 this.getLeft(), this.getTop(), this.getWidth(), this.getHeight()); 116}; 117 118/** 119 * Called once the mouse has been released, and the dragging is over. 120 */ 121ResizableVerticalSplitView.prototype.onDragSizerEnd = function(event) { 122 window.removeEventListener('mousemove', this.sizerMouseMoveListener_, true); 123 window.removeEventListener('mouseup', this.sizerMouseUpListener_, true); 124 125 this.sizerMouseMoveListener_ = null; 126 this.sizerMouseUpListener_ = null; 127 128 event.preventDefault(); 129}; 130