1 /*
  2  * ***** BEGIN LICENSE BLOCK *****
  3  * Zimbra Collaboration Suite Web Client
  4  * Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc.
  5  *
  6  * The contents of this file are subject to the Common Public Attribution License Version 1.0 (the "License");
  7  * you may not use this file except in compliance with the License.
  8  * You may obtain a copy of the License at: https://www.zimbra.com/license
  9  * The License is based on the Mozilla Public License Version 1.1 but Sections 14 and 15
 10  * have been added to cover use of software over a computer network and provide for limited attribution
 11  * for the Original Developer. In addition, Exhibit A has been modified to be consistent with Exhibit B.
 12  *
 13  * Software distributed under the License is distributed on an "AS IS" basis,
 14  * WITHOUT WARRANTY OF ANY KIND, either express or implied.
 15  * See the License for the specific language governing rights and limitations under the License.
 16  * The Original Code is Zimbra Open Source Web Client.
 17  * The Initial Developer of the Original Code is Zimbra, Inc.  All rights to the Original Code were
 18  * transferred by Zimbra, Inc. to Synacor, Inc. on September 14, 2015.
 19  *
 20  * All portions of the code are Copyright (C) 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2013, 2014, 2016 Synacor, Inc. All Rights Reserved.
 21  * ***** END LICENSE BLOCK *****
 22  */
 23 
 24 /**
 25  * Creates a sash.
 26  * @constructor
 27  * @class
 28  * A sash is a thin moveable border between two components that can be moved in
 29  * order to change the sizes of the elements on either side. Those one one side
 30  * will become larger, and those on the other side will become smaller.
 31  * 
 32  * @param {hash}	params		a hash of parameters
 33  * @param {DwtComposite}      params.parent		the parent widget
 34  * @param {DwtSash.HORIZONTAL_STYLE|DwtSash.VERTICAL_STYLE}      [params.style=DwtSash.VERTICAL_STYLE]			the sash style
 35  * @param {string}      params.className		the CSS class
 36  * @param    {number}	[params.threshold=1]		minimum movement (in pixels) that forces a UI update. Clients will likely want to set it higher.
 37  * @param {constant}       params.posStyle		the positioning style (see {@link DwtControl})
 38  * 
 39  * @extends		DwtControl
 40  */
 41 DwtSash = function(params) {
 42 	params = Dwt.getParams(arguments, DwtSash.PARAMS);
 43 	params.className = params.className || "DwtSash";
 44 	params.posStyle = params.posStyle || DwtControl.ABSOLUTE_STYLE;
 45 	DwtControl.call(this, params);
 46 
 47     var htmlElement = this.getHtmlElement();
 48     var templatePrefix = "dwt.Widgets#";
 49     if (!params.style || params.style != DwtSash.HORIZONTAL_STYLE) {
 50 		this._style = DwtSash.VERTICAL_STYLE;
 51 		htmlElement.style.cursor = AjxEnv.isIE ? "row-resize" : "s-resize";
 52 		htmlElement.innerHTML = AjxTemplate.expand(templatePrefix + "DwtVerticalSash");
 53 	} else {
 54 		this._style = DwtSash.HORIZONTAL_STYLE;
 55 		htmlElement.style.cursor = AjxEnv.isIE ? "col-resize" : "w-resize";
 56 		htmlElement.innerHTML = AjxTemplate.expand(templatePrefix + "DwtHorizontalSash");
 57 	}
 58 	this._threshold = (params.threshold > 0) ? params.threshold : 1;
 59 
 60 	this._captureObj = new DwtMouseEventCapture({
 61 		targetObj:this,
 62 		id:"DwtSash",
 63 		mouseOverHdlr:DwtSash._mouseOverHdlr,
 64 		mouseDownHdlr:DwtSash._mouseDownHdlr,
 65 		mouseMoveHdlr:DwtSash._mouseMoveHdlr,
 66 		mouseUpHdlr:DwtSash._mouseUpHdlr,
 67 		mouseOutHdlr:DwtSash._mouseOutHdlr
 68 	});
 69 	this.setHandler(DwtEvent.ONMOUSEDOWN, DwtSash._mouseDownHdlr);
 70 	this.setHandler(DwtEvent.ONMOUSEOVER, DwtSash._mouseOverHdlr);
 71 	this.setHandler(DwtEvent.ONMOUSEOUT, DwtSash._mouseOutHdlr);
 72 
 73 	this.setZIndex(Dwt.Z_VIEW);
 74 }
 75 
 76 DwtSash.PARAMS = ["parent", "style", "className", "threshold", "posStyle"];
 77 
 78 DwtSash.prototype = new DwtControl;
 79 DwtSash.prototype.constructor = DwtSash;
 80 
 81 DwtSash.prototype.toString = 
 82 function() {
 83 	return "DwtSash";
 84 }
 85 
 86 /**
 87  * Defines the "horizontal" sash style.
 88  */
 89 DwtSash.HORIZONTAL_STYLE  = 1;
 90 /**
 91  * Defines the "vertical" sash style.
 92  */
 93 DwtSash.VERTICAL_STYLE = 2;
 94 
 95 // The callback function will be called with a proposed delta. It should return a value indication
 96 // how much of a delta was actually applied.
 97 DwtSash.prototype.registerCallback =
 98 function(callbackFunc, callbackObj) {
 99 	this._callbackFunc = callbackFunc;
100 	this._callbackObj = callbackObj;
101 };
102 
103 DwtSash._mouseOverHdlr =
104 function(ev) {
105 	var mouseEv = DwtShell.mouseEvent;
106 	mouseEv.setFromDhtmlEvent(ev);
107 	mouseEv._stopPropagation = true;
108 	mouseEv._returnValue = false;
109 	mouseEv.setToDhtmlEvent(ev);
110 	return false;	
111 }
112 
113 DwtSash._mouseDownHdlr =
114 function(ev) {
115 	var mouseEv = DwtShell.mouseEvent;
116 	mouseEv.setFromDhtmlEvent(ev, true);
117 	if (mouseEv.button != DwtMouseEvent.LEFT) {
118 		DwtUiEvent.setBehaviour(ev, true, false);
119 		return false;
120 	}
121 	DwtEventManager.notifyListeners(DwtEvent.ONMOUSEDOWN, mouseEv);
122 	var sash = mouseEv.dwtObj;
123 	if (sash._callbackFunc != null) {
124 		sash._captureObj.capture();
125 		sash._startCoord = (sash._style == DwtSash.HORIZONTAL_STYLE) 
126 				? mouseEv.docX : mouseEv.docY;
127 	}
128 	mouseEv._stopPropagation = true;
129 	mouseEv._returnValue = false;
130 	mouseEv.setToDhtmlEvent(ev);
131 	
132 	return false;	
133 }
134 
135 DwtSash._mouseMoveHdlr =
136 function(ev) {
137 	var mouseEv = DwtShell.mouseEvent;
138 	mouseEv.setFromDhtmlEvent(ev);	
139 	var delta = 0;
140 	var sash = DwtMouseEventCapture.getTargetObj();
141 	if (sash._style == DwtSash.HORIZONTAL_STYLE) {
142 		if (mouseEv.docX > 0 && mouseEv.docX != sash._startCoord)
143 			delta = mouseEv.docX - sash._startCoord;
144 	} else  {
145 		if (mouseEv.docY > 0 && mouseEv.docY != sash._startCoord)
146 			delta = mouseEv.docY - sash._startCoord;
147 	}
148 		
149 	if (Math.abs(delta) >= sash._threshold) {
150 		if (sash._callbackObj != null)
151 			delta = sash._callbackFunc.call(sash._callbackObj, delta);
152 		else 
153 			delta = sash._callbackFunc(delta);		
154 		sash._startCoord += delta;
155 		// If movement happened, then shift our location by the actual amount of movement
156 		if (delta != 0 && sash.getHtmlElement().style.position == Dwt.ABSOLUTE_STYLE) {
157 			if (sash._style == DwtSash.HORIZONTAL_STYLE)
158 				sash.setLocation(sash.getLocation().x + delta, Dwt.DEFAULT);
159 			else
160 				sash.setLocation(Dwt.DEFAULT, sash.getLocation().y + delta);
161 		}
162 	}
163 	mouseEv._stopPropagation = true;
164 	mouseEv._returnValue = false;
165 	mouseEv.setToDhtmlEvent(ev);
166 	return false;	
167 }
168 
169 DwtSash._mouseUpHdlr =
170 function(ev) {
171 	var mouseEv = DwtShell.mouseEvent;
172 	mouseEv.setFromDhtmlEvent(ev);	
173 	if (mouseEv.button != DwtMouseEvent.LEFT) {
174 		DwtUiEvent.setBehaviour(ev, true, false);
175 		return false;
176 	}
177 
178 	var sash = DwtMouseEventCapture.getTargetObj();
179 	if (sash._callbackFunc != null) {
180 		DwtMouseEventCapture.getCaptureObj().release();
181 	}
182 
183 	sash.notifyListeners(DwtEvent.ONMOUSEUP, mouseEv);
184 	mouseEv._stopPropagation = true;
185 	mouseEv._returnValue = false;
186 	mouseEv.setToDhtmlEvent(ev);
187 	return false;	
188 }
189 
190 DwtSash._mouseOutHdlr =
191 function(ev) {
192 	var mouseEv = DwtShell.mouseEvent;
193 	mouseEv.setFromDhtmlEvent(ev);
194 	mouseEv._stopPropagation = true;
195 	mouseEv._returnValue = false;
196 	mouseEv.setToDhtmlEvent(ev);
197 	return false;	
198 }
199 
200