// splitter.js

/***********************************************************************************************************************************
									PUBLIC (goes into API)
***********************************************************************************************************************************/

try {
	document.execCommand("BackgroundImageCache", false, true);//http://blogs.MDA.com/blogs/rumen_stankov/archive/2006/11/05/392.aspx
} catch (e) {

}

function MdSplitter (config) 
{

	config["logLevel"] = eval(config["logLevel"]);

	this.Log = new MdControlsNamespace.Log(config["logLevel"], true);
	
	this.ID = config["ID"];

	if (typeof(MdControlsNamespace.__splitters__) == "undefined")
	{
		MdControlsNamespace.__splitters__ = [];
	}
	
	// dispose the "old" splitters after callback
	if (MdControlsNamespace.__splitters__[this.ID] )
	{
		this.Log.Debug(["MdSplitter dispose the old splitter. ID[%d]", this.ID]);
		MdControlsNamespace.__splitters__[this.ID].Dispose();
	}
	
	// set/update the reference to the current splitter
	MdControlsNamespace.__splitters__[this.ID] = this;

	this.panes 					= [];
	this.panesByIndex			= [];
	this.panesById				= [];
	this.splitBars 				= [];
	this.splitBarsByIndex		= [];
	this.splitBarsById 			= [];
	this.splitBarsByItemIndex	= [];

	this.config = config;

	// init helper objects
	this.browser = MdControlsNamespace.Browser;
	this.screen  = MdControlsNamespace.Screen;
	this.box     = window.MdControlsNamespace.Box;
	MdControlsNamespace.EventMixin.Initialize(this);
	MdControlsNamespace.DomEventMixin.Initialize(this);

	this.heightOffset = config["heightOffset"];
	
	// init FullScreenMode
	this.fullScreenMode = config["fullScreenMode"];
	if (this.fullScreenMode) 
	{
		try {
			document.body.style.height="100%";
			document.documentElement.style.height="100%";
			document.forms[0].style.height="100%";
		} catch (e){}
	}
	
	this.resizeMode = config["resizeMode"];
	this.resizeStep = config["resizeStep"];

	this.parentPaneId = config["parentPaneId"];

	// init splitter events	
	this.supportedEvents = [
							"OnClientLoaded",
							"OnClientResized",
							"OnClientBeforeResize"
							];
	
	for (var i=0; i< this.supportedEvents.length; i ++) 
	{
		this[this.supportedEvents[i]] = config[this.supportedEvents[i]]; 
	}

	this.borderSize      = (this.IsNested()) ? 0 : config["borderSize"];
	this.splitBarsSize   = config["splitBarsSize"];
	this.panesBorderSize = config["panesBorderSize"];
	
	this.width  = config["width"];
	if (this.width.indexOf('px') > -1) 
	{
		this.width = parseInt(this.width, 10);
	}

	this.height = config["height"];
	if (this.height.indexOf('px') > -1) 
	{
		this.height = parseInt(this.height, 10);
	}
	
	this.originalDimensions = {
		width  : this.width,
		height : this.height		
	}
	
	this.orientation = config["orientation"];	
	
	this.resizeWithBrowserWindow = config["resizeWithBrowserWindow"];
	this.resizeWithParentPane	 = config["resizeWithParentPane"];
	this.visibleDuringInit		 = config["visibleDuringInit"];


	var viewPortSize = this.screen.GetViewPortSize() 
	
	this.WindowWidth=viewPortSize.width;
	this.WindowHeight=viewPortSize.height;
	
	this.initialSizeSet = false;
	
	this.containerElement = document.getElementById('Md_SPLITTER_' + this.ID);
	this.wrapperElement = document.getElementById(this.ID);
	
	if ((typeof(__MdSplitter__page_loaded) != "undefined" && __MdSplitter__page_loaded) || "complete" == document.readyState)
	{
		// update the splitter reference of the parent pane after callback
		if (this.IsNested() && this.resizeWithParentPane)
		{
			try {
				var parentPane = window[this.parentPaneId];
				if (parentPane && parentPane.Inited)
				{
					parentPane.childSplitter = this;
					window["MdPaneConfig_" + this.parentPaneId].childSplitterID = this.ID; 
				}
			} catch (e) {}
		}
		
		// seems like the css is not rendered still when make the splitter visible with AJAX -> #7089 
		var self = this;
		var t = function ()
		{
			self.Init();
		}		
		setTimeout(t,10);
	} 
	else
	{
		MdControlsNamespace.InitSplitterOnLoad(this);
		this.Log.Debug(["Splitter Attach to load event to init ID[%d]", this.ID]);
	}
}



MdSplitter.prototype.Init = function () 
{
	if (this.Inited) return;

	this.Log.Debug(["Splitter.Init start ID[%d]", this.ID]);

	// initialize pane objects
	var panes = this.config["panes"];
	for (var i=0; i < panes.length; i ++) 
	{
		var paneConfig = window["MdPaneConfig_" + panes[i]];
		paneConfig["splitter"] = this;
		paneConfig["index"] = i;
		paneConfig["logLevel"] = this.config["logLevel"];
		
		var paneObj = new MdSplitter_Pane(paneConfig);
		this.addPane(paneObj);

	}
	
	// initialize splitbar objects
	var splitBars = this.config["splitBars"];
	for (var i=0; i < splitBars.length; i ++) 
	{
		var splitBarConfig = window["MdSplitBarConfig_" + splitBars[i]];
		splitBarConfig["splitter"] = this;
		splitBarConfig["liveResize"] = this.config["liveResize"];
		splitBarConfig["index"] = i;
		splitBarConfig["logLevel"] = this.config["logLevel"];
		
		var splitBarObj = new MdSplitter_SplitBar(splitBarConfig);
		this.addSplitBar(splitBarObj);

	}

	
	// init childs	
	for (var i=0; i < this.splitBars.length; i ++)
	{
		this.splitBars[i].Init();
	}

	for (var i=0; i < this.panes.length; i++)
	{
		this.panes[i].Init();
	}

	if (this.isDisplayed())
	{
		this.calculateInitialSize();
	}

	this.handleToResizeEvent = false;
	
	if (
		this.originalDimensions.width.toString().indexOf('%') > -1 ||
		this.originalDimensions.height.toString().indexOf('%') > -1
	) 
	{
		if (!(this.arePanesFixedSize() && !this.containsInitialRelativeSizedPanes()))
		{
			this.handleToResizeEvent = true;
		}
	}
	
	var containerElement = this.getWrapperElement()
		
	var self = this;
	containerElement.MdShow = function ()
	{
		var t = function () {
			if (!self.isDisplayed()) return;
			self.HandleResize(true);
		}
		window.setTimeout(t,10);
	}

	if (this.handleToResizeEvent && this.resizeWithBrowserWindow && !this.IsNested()) 
	{
		this.Log.Debug(["Splitter.setSplitterSize attach to the resize event. ID[%d]", this.ID]);
		this.AttachDomEvent(window, "resize", "_HandleResize");
		
		containerElement.MdResize = function ()
		{
			var t = function () {
				if (!self.isDisplayed()) return;
				
				self.HandleResize(true);
			}
			window.setTimeout(t,10);
		}
	}
	
	this.AttachDomEvent(window, "unload", "Dispose");

	this.Inited = true;

	this.Log.Debug(["Splitter.Init End ID[%d].", this.ID]);

	this.RaiseEvent('OnClientLoaded', {splitterObj : this});
}

MdSplitter.prototype.Dispose = function () 
{	
	this.DisposeDomEventHandlers();

	for (var i=0; i < this.panes.length; i ++){
		this.panes[i].Dispose();
	}

	for (var i=0; i < this.splitBars.length; i ++) 
	{
		this.splitBars[i].Dispose();
	}

	var containerElement = this.getWrapperElement();
	if (containerElement != null ) {
		containerElement.MdShow = null;
		containerElement.MdResize = null;	
	}

	for (var i in this)
	{
		this[i] = null;
	}
}

MdSplitter.prototype.IsNested = function () 
{
	return this.parentPaneId != null;
}

MdSplitter.prototype.SetResizeMode = function (resizeMode)
{
	this.resizeMode = resizeMode;
}

MdSplitter.prototype.GetResizeMode = function ()
{
	return this.resizeMode;
}

MdSplitter.prototype.SetHeightOffset = function (heightOffset)
{
	this.heightOffset = heightOffset;
}

MdSplitter.prototype.GetHeightOffset = function ()
{
	return this.heightOffset;
}


MdSplitter.prototype.GetWidth = function () 
{
	return this.width;
}

MdSplitter.prototype.GetHeight = function () 
{
	return this.height;
}

MdSplitter.prototype.GetInnerWidth = function () 
{
	return this.GetWidth() - this.getBordersDiff();
}

MdSplitter.prototype.GetInnerHeight = function () 
{
	return this.GetHeight() - this.getBordersDiff();
}
MdSplitter.prototype.GetPanes = function () 
{
	return this.panes;
}

MdSplitter.prototype.Resize = function (width, height, skipEvent) 
{
	
	if (!this.initialSizeSet) 
	{
		this.calculateInitialSize();
	}
	
	var startTime = new Date();
	if (!skipEvent) { 
		if (!this.RaiseEvent('OnClientBeforeResize', {
														splitterObj   : this, 
														newWidth      : width, 
														newHeight     : height
													}))
		{
			return false;		
		}
	}
	
	this.Log.Debug(["Splitter.Resize time#1 [%d], [%d]", startTime - new Date(), this.ID]);
		
	this.Log.Debug(["Splitter.Resize width[%d], height[%d], currentWidth[%d], currentHeight[%d], splID[%d]", width, height, this.GetWidth(), this.GetHeight(), this.ID]);
	
	var varSizeChanged = false;
	var fixedSizeChanged = false;
	var delta = 0;
	
	var oldWidth  = this.GetWidth();
	var oldHeight = this.GetHeight();
	
	if (width != null && width != oldWidth) {

		var deltaW = width - oldWidth;

		this.setContainerOuterWidth(width);

		this.width = width;
		
		if (this.IsVertical()) 
		{
			delta = deltaW;
			varSizeChanged = true;
		}
		else 
		{
			fixedSizeChanged = true;
		}
	}

	if (height != null && height != oldHeight)
	{
		var deltaH = height - this.GetHeight();
		
		this.setContainerOuterHeight(height);
		this.height = height;
		
		if (!this.IsVertical()) 
		{
			delta = deltaH;
			varSizeChanged = true;
		}
		else 
		{
			fixedSizeChanged = true;
		}
	}

	// if the fixed size is changed - change it to all panes
	if (fixedSizeChanged)
	{
		for (var i=0; i < this.panes.length; i ++)
		{
			var pane = this.panes[i];
			
			if (pane.IsCollapsed()) continue;
			
			var paneOldWidth = pane.GetWidth();
			var paneOldHeight = pane.GetHeight();
			
			if (this.IsVertical())
			{
				pane.SetHeight(height);
			} 
			else 
			{
				pane.SetWidth(width);					
			}

			pane.RaiseEvent("OnClientPaneResized", {
									paneObj 	: pane, 
									
									oldWidth 	: paneOldWidth, 
									oldHeight	: paneOldHeight,
									 
									newWidth 	: pane.GetWidth(), 
									newHeight	: pane.GetHeight()
								});
			pane.callMdResize();
		}		
	}

	// if the variable size is change - resize the panes variable size
	if (varSizeChanged) 
	{

		this.Log.Debug(['Splitter.Resize delta is [%d], splID[%d]', delta, this.ID]);

		if (this.containsInitialFreeSizedPanes()) { // set all the delta to the free sized panes, otherwise resize proportional

			var freeSizedPanes = this.getInitialFreeSizedPanes();
			var freeSizedPanesCount = freeSizedPanes.length;

			var deltaPerPane = parseInt(delta / freeSizedPanesCount, 10);

			this.Log.Debug(['Splitter.Resize Free sized panes detected  splID[%d]. Pane delta[%d]', this.ID, deltaPerPane]);

			var deltaLeft = 0;

			for (var i=0; i < freeSizedPanes.length; i ++)
			{
				var pane = freeSizedPanes[i];

				var paneAvailDelta = (deltaPerPane > 0) ? pane.getAvailIncreaseDelta() : pane.getAvailDecreaseDelta();

				var deltaToApply = deltaPerPane;
				if (paneAvailDelta < Math.abs(deltaPerPane))
				{
					deltaToApply = paneAvailDelta * ((deltaPerPane > 0) ? 1 : -1);
					deltaLeft += deltaPerPane - deltaToApply;
				}
				
				this.Log.Debug(['Splitter.Resize delta[%d], paneAvailDelta[%d], pane[%d]', deltaToApply, paneAvailDelta, pane.ID]);
				
				var paneNewSize = pane.getVarSize() + deltaToApply;

				var paneOldHeight = pane.GetHeight();
				var paneOldWidth = pane.GetWidth();
				
				pane.setVarSize(paneNewSize); 
				
				if (this.Inited && !skipEvent) 
				{
					pane.RaiseEvent("OnClientPaneResized", {
							paneObj 	: pane, 
							
							oldWidth 	: paneOldWidth, 
							oldHeight	: paneOldHeight,
							 
							newWidth 	: pane.GetWidth(), 
							newHeight	: pane.GetHeight()
						});
					pane.callMdResize();
				}
			}

			this.Log.Debug(['Splitter.Resize deltaLeft[%d] after resize of the free panes', deltaLeft]);

			this.fixPanesRounding(freeSizedPanes);

			// the free sized panes can not get all the delta - so resize the rest of the panes
			if (deltaLeft != 0)
			{
				deltaLeft *= -1; 
				this.resizeProportional(deltaLeft, null, MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward);
			}
		} 
		else
		{
			delta *= -1; 
			this.resizeProportional(delta, null, MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward);
		}	
	}
	
	if (!skipEvent) {
		this.RaiseEvent('OnClientResized', {
												splitterObj   : this, 
												newWidth      : this.GetWidth(), 
												newHeight     : this.GetHeight(),
												oldWidth      : oldWidth,
												oldHeight     : oldHeight
										   });
	
	}

	return true;
}

MdSplitter.prototype.GetEndPane = function () 
{
	return this.GetPaneByIndex(this.panes.length-1);
}

MdSplitter.prototype.GetStartPane = function () 
{
	return this.GetPaneByIndex(0);
}

// return the height of the splitter and the splitter bar height
MdSplitter.prototype.IsVertical = function () 
{
	return (this.orientation == MdSplitterNamespace.Md_SPLITTER_ORIENTATION.VERTICAL);
}

// loop thru all the panes and sum their minWidth
MdSplitter.prototype.GetMinWidth = function (startPaneIndex, endPaneIndex) 
{
	var calculatedMinWidth = this.getMinMaxSize(startPaneIndex, endPaneIndex, true, true);
	
	this.Log.Debug(['Splitter.GetMinWidth calculatedMinWidth[%d]', calculatedMinWidth]);
	return calculatedMinWidth;
}

// loop thru all the panes and sum their maxWidth
MdSplitter.prototype.GetMaxWidth = function (startPaneIndex, endPaneIndex) 
{
	var calculatedMaxWidth = this.getMinMaxSize(startPaneIndex, endPaneIndex, false, true);
	
	this.Log.Debug(['Splitter.GetMaxWidth calculatedMaxWidth[%d]', calculatedMaxWidth]);
	return calculatedMaxWidth;
}

// loop thru all the panes and sum their minHeight
MdSplitter.prototype.GetMinHeight = function (startPaneIndex, endPaneIndex) 
{
	var calculatedMinHeight = this.getMinMaxSize(startPaneIndex, endPaneIndex, true, false);
		
	this.Log.Debug(['Splitter.GetMinHeight calculatedMinHeight[%d]', calculatedMinHeight]);
	return calculatedMinHeight;
}

// loop thru all the panes and sum their maxHeight
MdSplitter.prototype.GetMaxHeight = function (startPaneIndex, endPaneIndex) 
{
	var calculatedMaxHeight = this.getMinMaxSize(startPaneIndex, endPaneIndex, false, false);	

	this.Log.Debug(['Splitter.GetMaxHeight calculatedMaxHeight[%d]', calculatedMaxHeight]);
	return calculatedMaxHeight;
}

MdSplitter.prototype.GetPaneByIndex = function (paneIndex) 
{
	return this.panesByIndex[paneIndex];
}

MdSplitter.prototype.GetPaneById = function (paneID) 
{
	return this.panesById[paneID];
}

MdSplitter.prototype.GetSplitBarByIndex = function (index) 
{
	return this.splitBarsByIndex[index];
}

// get the splitbar by its index in the items collection of the MdSplitter control
MdSplitter.prototype.getSplitBarByItemIndex = function (index) 
{
	return this.splitBarsByItemIndex[index];
}

MdSplitter.prototype.GetSplitBarById = function (splitBarID) 
{
	return this.splitBarsById[splitBarID];
}

MdSplitter.prototype.GetSplitBars = function () 
{
	return this.splitBars;
}


MdSplitter.prototype.SetWidth = function (width)
{
	this.setWidth(width);
}

MdSplitter.prototype.SetHeight = function (height)
{
	this.setHeight(height);
}

MdSplitter.prototype.GetContainerElement = function ()
{
	return this.containerElement;
}

MdSplitter.prototype.getWrapperElement = function ()
{
	return this.wrapperElement || document.getElementById(this.ID);
}


/***********************************************************************************************************************************
									PRIVATE
***********************************************************************************************************************************/
MdSplitter.prototype.resizeAdjacentPane = function (delta, paneObj, resizeDirection) 
{
	if (delta == 0) return;
	var adjacentPaneObj = this.getAvailAdjacentPane(paneObj.Index, resizeDirection);
	if (adjacentPaneObj == null) 
	{
		this.Log.Warning(['Splitter.resizeAdjacentPane: Can not find suitable adjacent pane. PaneId[%d], ResizeDirection[%d] RETURN.', paneObj.ID,resizeDirection ]);

		return false;
	}
	
	if (!this.isCollapseMode && !this.isExpandMode) {

		if (!paneObj.RaiseEvent('OnClientBeforePaneResize', {
																	paneObj   : paneObj, 
																	delta     : delta, 
																	direction : resizeDirection
																}))
		{
			return false;		
		}

		if (!adjacentPaneObj.RaiseEvent('OnClientBeforePaneResize', {
																	paneObj   : adjacentPaneObj, 
																	delta     : delta * -1, 
																	direction : resizeDirection
																}))
		{
			return false;		
		}
	}



	this.Log.Debug(['Splitter.resizeAdjacentPane: Found Adjacent pane[%d], for pane[%d].', adjacentPaneObj.ID, paneObj.ID]);
	
	var paneOldWidth = paneObj.GetWidth();
	var paneOldHeight = paneObj.GetHeight();
	
	var adjPaneOldWidth = adjacentPaneObj.GetWidth();
	var adjPaneOldHeight = adjacentPaneObj.GetHeight();
		
	var	paneNewSize = paneObj.getVarSize() + delta;
	var adjacentPaneNewSize = adjacentPaneObj.getVarSize() - delta;
	
	this.Log.Debug(['Splitter.resizeAdjacentPane: Set PaneSize[%d], AdjacentSize[%d], AdjacentIndex[%d]', paneNewSize, adjacentPaneNewSize, adjacentPaneObj.ID]);
	
	// update current pane
	paneObj.setVarSize(paneNewSize);

	// update adjacent pane
	adjacentPaneObj.setVarSize(adjacentPaneNewSize);
	
	if (!this.isCollapseMode && !this.isExpandMode) { // dont fire the events if we are in collapse mode
		paneObj.RaiseEvent("OnClientPaneResized", {paneObj : paneObj, oldWidth : paneOldWidth, oldHeight:paneOldHeight, newWidth : paneObj.GetWidth(), newHeight:paneObj.GetHeight()});
		paneObj.callMdResize();
	}
	
	adjacentPaneObj.RaiseEvent("OnClientPaneResized", {paneObj : adjacentPaneObj, oldWidth : adjPaneOldWidth, oldHeight:adjPaneOldHeight, newWidth : adjacentPaneObj.GetWidth(), newHeight:adjacentPaneObj.GetHeight()});

	adjacentPaneObj.callMdResize();
	
	return true;
}

MdSplitter.prototype.resizeEndPane = function (delta, targetPane, resizeDirection) 
{
	if (delta == 0) return;
	var endPaneObj = (resizeDirection == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) ? this.GetEndPane() : this.GetStartPane();

	if (!this.isCollapseMode && !this.isExpandMode) {
		
		if (!targetPane.RaiseEvent('OnClientBeforePaneResize', {
																	paneObj   : targetPane, 
																	delta     : delta, 
																	direction : resizeDirection
																}))
		{
			return false;		
		}
		
		if (!endPaneObj.RaiseEvent('OnClientBeforePaneResize', {
																	paneObj   : endPaneObj, 
																	delta     : delta * -1, 
																	direction : resizeDirection
																}))
		{
			return false;		
		}
	}

	
	var paneOldWidth = targetPane.GetWidth();
	var paneOldHeight = targetPane.GetHeight();
	
	var endPaneOldWidth = endPaneObj.GetWidth();
	var endPaneOldHeight = endPaneObj.GetHeight();

	// update current pane
	var targetPaneNewSize = targetPane.getVarSize() + delta;
	targetPane.setVarSize(targetPaneNewSize);

	var endPaneNewSize = endPaneObj.getVarSize() - delta 
	
	// update adjacent pane
	endPaneObj.setVarSize(endPaneNewSize);

	this.Log.Debug(['Splitter.resizeEndPane: Set current pane size[%d], end pane size[%d]', targetPaneNewSize, endPaneNewSize]);

	if (!this.isCollapseMode && !this.isExpandMode) { // dont fire the events if we are in collapse mode
		targetPane.RaiseEvent("OnClientPaneResized", {paneObj : targetPane, oldWidth : paneOldWidth, oldHeight:paneOldHeight, newWidth : targetPane.GetWidth(), newHeight:targetPane.GetHeight()});
		targetPane.callMdResize();
	}

	endPaneObj.RaiseEvent("OnClientPaneResized", {paneObj : endPaneObj, oldWidth : endPaneOldWidth, oldHeight:endPaneOldHeight, newWidth : endPaneObj.GetWidth(), newHeight:endPaneObj.GetHeight()});

	
	endPaneObj.callMdResize();
	
	return true;
}

MdSplitter.prototype.resizeProportional = function (delta, targetPane, direction) 
{
	if (delta == 0) return;

	var raiseResizeEvents = (this.isCollapseMode || this.isExpandMode) ? false : true;

	this.Log.Debug(['Splitter.resizeProportional - raiseResizeEvents[%d]', raiseResizeEvents]);
	
	if (raiseResizeEvents && targetPane != null) {

		if (!targetPane.RaiseEvent('OnClientBeforePaneResize', {
																	paneObj   : targetPane, 
																	delta     : delta, 
																	direction : direction
																}))
		{
			return;
		}
	}

	var absDelta = Math.abs(delta);
	var panesSize = 0;
	var isDecreaseMode = (delta > 0);

	var startPaneIndex = (targetPane != null) ? ((direction == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) ? targetPane.Index + 1 : targetPane.Index - 1) : 0 ;
	
	var arrDepPanes = [];
	if (direction == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) 
	{
		for (var i = startPaneIndex; i < this.panes.length; i ++) 
		{
			var oPane = this.GetPaneByIndex(i);
			arrDepPanes[arrDepPanes.length] = oPane;
			panesSize += oPane.getVarSize();
		}
	}
	else
	{
		for (var i = startPaneIndex; i >= 0; i --) 
		{
			var oPane = this.GetPaneByIndex(i);
			arrDepPanes[arrDepPanes.length] = oPane;
			panesSize += oPane.getVarSize();
		}
	}
	
	// we need at least 2 panes so we can resize proportionaly - oterwise - resize adjacent
	if (arrDepPanes.length < 2 && targetPane != null) {
		this.Log.Debug(['Splitter.resizeProportional - no enough panes for propotional resize. Do AdjacentPane resize.']);	
		this.resizeAdjacentPane(delta, targetPane, direction);
		return;		
	}
	
	this.Log.Debug(['Splitter.resizeProportional - delta[%d], panesSize[%d], decreaseMode[%d]', delta, panesSize, isDecreaseMode]);
	
	var paneIndexesToSkip = []; //store here the panes that are already resized at the max and can not be resized more
	
	do {
		var currentPanesVarSize = panesSize;
	
		var deltaLeft = 0;
		for (var i = 0; i < arrDepPanes.length; i ++) 
		{
			if (paneIndexesToSkip[i]) continue;

			var currentPane = arrDepPanes[i];

			if (currentPane.IsCollapsed() || currentPane.IsLocked())
			{
				paneIndexesToSkip[i] = true;
				continue;		
			}

			var paneSize      = currentPane.getVarSize();
			var paneAvailDelta = (isDecreaseMode) ? currentPane.getAvailDecreaseDelta() : currentPane.getAvailIncreaseDelta();
			var paneWeight     = paneSize / currentPanesVarSize;
			var paneDelta      = absDelta * paneWeight;

			this.Log.Debug(['Splitter.resizeProportional AllDelta[%d], paneId[%d], paneSize[%d], paneWeight[%d],\\n paneAvailDelta[%d], paneNeededDelta[%d], panesSize[%d]', absDelta, currentPane.ID, paneSize, paneWeight, paneAvailDelta, paneDelta, panesSize]);
			
			if ((paneDelta - paneAvailDelta) > 0) 
			{
				paneIndexesToSkip[i] = true;
			}
			
			var deltaToApply = Math.min(paneDelta, paneAvailDelta);

			if (isDecreaseMode) deltaToApply *= -1;
			
			var currentPaneDelta = paneSize + deltaToApply;
			
			if (raiseResizeEvents) {
				if (!currentPane.RaiseEvent('OnClientBeforePaneResize', {
																			paneObj   : currentPane, 
																			delta     : parseInt(currentPaneDelta), 
																			direction : direction
																		}))
				{
					paneIndexesToSkip[i] = true;
					continue;		
				}
			}
			
			deltaLeft += paneDelta - Math.abs(deltaToApply);
			this.Log.Debug(['Splitter.resizeProportional Applying paneDelta[%d], deltaLeft[%d]', deltaToApply, deltaLeft]);
			
			
			var paneOldW = currentPane.GetWidth();	
			var paneOldH = currentPane.GetHeight();

			currentPane.setVarSize(currentPaneDelta);
			
			currentPane.RaiseEvent("OnClientPaneResized", 
					{
						paneObj   : currentPane, 
						oldWidth  : paneOldW, 
						oldHeight : paneOldH, 
						newWidth  : currentPane.GetWidth(),
						newHeight : currentPane.GetHeight()
					});
			currentPane.callMdResize();
			
			panesSize += (paneIndexesToSkip[i]) ? (-1) * currentPane.getVarSize() + deltaToApply : deltaToApply;
		}

		absDelta = deltaLeft;

	} while (deltaLeft != 0)
	
	
	if (targetPane != null) 
	{
		var targetPaneOldW = targetPane.GetWidth();
		var targetPaneOldH = targetPane.GetHeight();
		
		targetPane.setVarSize(targetPane.getVarSize() + delta);
		
		if (raiseResizeEvents) {
			targetPane.RaiseEvent("OnClientPaneResized", {
									paneObj   : targetPane, 
									oldWidth  : targetPaneOldW, 
									oldHeight : targetPaneOldH, 
									newWidth  : targetPane.GetWidth(),
									newHeight : targetPane.GetHeight()}
							  );
			targetPane.callMdResize();
		}
	}

	this.fixPanesRounding(arrDepPanes);
}

MdSplitter.prototype.fixPanesRounding = function (arrPanes) 
{
	if (!arrPanes) arrPanes = this.GetPanes();
	
	// check the rounding now
	var splitterPanesSize = (this.IsVertical()) ? this.getPanesAvailWidth() : this.getPanesAvailHeight() ;
	 
	this.Log.Debug(['Splitter.fixPanesRounding Splitter panes size[%d], splID[%d]', splitterPanesSize, this.ID]);
	 
	var panes = this.GetPanes();
	var realPanesSize = 0;
	for (var i=0; i < panes.length; i ++) {

		var size = panes[i].getVarSize();
		this.Log.Debug(['Splitter.fixPanesRounding panes size[%d], paneID[%d], splID[%d]', size, panes[i].ID, this.ID]);
		realPanesSize += size;
	}

	var delta = splitterPanesSize - realPanesSize;
	if (delta != 0) { // round err found
		
		this.Log.Warning(['Splitter.fixPanesRounding Found rounding error delta[%d], splID[%d]', delta, this.ID]);
		
		// find a pane which can take the rounding
		for (var i=0; i < arrPanes.length; i ++ )
		{
			var pane = arrPanes[i];
			if (pane.IsCollapsed() || pane.IsLocked())
			{
				continue;
			} 
			
			if (!pane.RaiseEvent('OnClientBeforePaneResize', {
																			paneObj   : pane, 
																			delta     : delta, 
																			direction : MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward
																		}))
			{
				continue;		
			}
			
			var paneOldW = pane.GetWidth();
			var paneOldH = pane.GetHeight();
			var doResizePane = false;
			if (delta > 0) 
			{
				if (pane.getAvailIncreaseDelta() > 0)
				{
					doResizePane = true;
				}
			} 
			else 
			{
				if (pane.getAvailDecreaseDelta() > 0)
				{
					doResizePane = true;
				}
			}
			
			if (doResizePane) 
			{
				this.Log.Warning(['Splitter.fixPanesRounding Applying round correction[%d], paneID[%d]', delta, pane.ID]);
				
				pane.setVarSize(pane.getVarSize() + delta);
				
				pane.RaiseEvent("OnClientPaneResized", {
								paneObj   : pane, 
								oldWidth  : paneOldW, 
								oldHeight : paneOldH, 
								newWidth  : pane.GetWidth(),
								newHeight : pane.GetHeight()}
						  );
						  
				pane.callMdResize();
				
				break;
			}
		}
	}
}

MdSplitter.prototype.addPane = function (paneObj) 
{
	//this.Log.Debug(["Splitter.addPane paneID[%d], splitterID[%d]", paneObj.ID, this.ID]);
	this.panes[this.panes.length] 		= paneObj;
	this.panesByIndex[paneObj.Index] 	= paneObj;
	this.panesById[paneObj.ID] 			= paneObj;	
}

MdSplitter.prototype.addSplitBar = function (splitBarObj) 
{
	this.splitBars[this.splitBars.length] = splitBarObj;
	this.splitBarsByIndex[splitBarObj.Index] = splitBarObj;
	this.splitBarsById[splitBarObj.ID] = splitBarObj;
	this.splitBarsByItemIndex[splitBarObj.indexInSplitItems] = splitBarObj;
}

MdSplitter.prototype.setWidth = function (width)
{

	if (width == this.width)
	{
		return;		
	}

	this.Log.Debug(["Splitter.setWidth: width[%d]", width]);

	var pxWidth = width;
	if (width.toString().indexOf('%') > -1) 
	{
		pxWidth = this.calculatePercentWidth(width);
	}
	
	pxWidth = parseInt(pxWidth, 10);
	if (isNaN(pxWidth)) return;

	this.Resize(pxWidth, null);	
}

MdSplitter.prototype.setHeight = function (height)
{
	
	if (height == this.height)
	{
		return;		
	}

	
	this.Log.Debug(["Splitter.setHeight ID[%d], height[%d]", this.ID, height]);
	
	var pxHeight = height;
	if (height.toString().indexOf('%') > -1)
	{
		pxHeight = this.calculatePercentHeight(height);
	}
	
	pxHeight = parseInt(pxHeight, 10);
	
	if (isNaN(pxHeight)) return;
	
	this.Resize(null, pxHeight);
}

MdSplitter.prototype.setContainerOuterWidth = function (pxWidth) 
{
	this.width = pxWidth;
	this.Log.Debug(["Splitter.setContainerOuterWidth width[%d], splID[%d]", pxWidth, this.ID]);
	
	this.box.SetOuterWidth(this.GetContainerElement(), pxWidth);
}

MdSplitter.prototype.setContainerOuterHeight = function (pxHeight) 
{
	this.height = pxHeight;
	
	this.Log.Debug(["Splitter.setContainerOuterHeight height[%d], splID[%d]", pxHeight, this.ID]);
	
	this.box.SetOuterHeight(this.GetContainerElement(), pxHeight);
}

MdSplitter.prototype.setContainerInnerWidth = function (pxWidth) 
{
	this.setContainerOuterWidth(pxWidth + this.getBordersDiff());
}

MdSplitter.prototype.setContainerInnerHeight = function (pxHeight) 
{
	this.setContainerOuterHeight(pxHeight + this.getBordersDiff());
}

MdSplitter.prototype.arePanesFixedSize = function ()
{
	var panes = this.GetPanes();
	for (var i=0; i < panes.length; i ++)
	{
		if (!panes[i].IsFixedSize())
		{
			return false;
		}
	}

	return true;
}

MdSplitter.prototype.containsFreeSizedPanes = function ()
{
	var panes = this.GetPanes();
	for (var i=0; i < panes.length; i ++)
	{
		if (panes[i].IsFreeSize()) return true;
	}
	return false;
}

MdSplitter.prototype.containsInitialRelativeSizedPanes = function ()
{
	if (this.containsInitialFreeSizedPanes()) return true;

	var panes = this.GetPanes();
	for (var i=0; i < panes.length; i ++)
	{
		if (panes[i].getOrigVarSize().indexOf('%')) return true;
	}
	return false;
}



MdSplitter.prototype.containsInitialFreeSizedPanes = function ()
{
	var panes = this.GetPanes();
	for (var i=0; i < panes.length; i ++)
	{
		if (panes[i].IsInitialFreeSize()) return true;
	}
	return false;
}


// all panes percent size
MdSplitter.prototype.arePanesPercenSize = function ()
{
	var panes = this.GetPanes();
	for (var i=0; i < panes.length; i ++)
	{
 		if (!panes[i].IsPercentSize())
		{
			return false;
		}
	}
	
	return true;
}
MdSplitter.prototype._HandleResize = function ()
{
	this.HandleResize(false);
}

MdSplitter.prototype.HandleResize = function (forceResize)
{

	if (!this.isDisplayed()) return;
	
	if (!this.initialSizeSet) 
	{
		this.calculateInitialSize();
	}

	var startTime = new Date();
	var now = new Date();

	if ((now - this.lastResize) < 150)
	{
		this.pendingResize = true;
		return;		
	}
	
	this.pendingResize = false;
	
	this.Log.Debug(["Splitter.ResizeHandler. ID [%d]", this.ID]);

	var viewPortSize = this.screen.GetViewPortSize() 
	
	var windowWidth	 = viewPortSize.width;
	var windowHeight = viewPortSize.height;

	if(!forceResize && this.WindowHeight == windowHeight && this.WindowWidth == windowWidth)
	{
		this.Log.Warning(["Splitter.ResizeHandler - skip resize due to same dimensions ID [%d]", this.ID]);
		return;
	}

	this.Log.Warning(["Splitter.ResizeHandler - windowW[%d] windowH[%d] ID [%d]", windowWidth,windowHeight, this.ID]);

	//this.Log.Debug(["Splitter.ResizeHandler . windowW[%d] windowH[%d] ID [%d]", windowWidth,windowHeight, this.ID]);
	this.WindowHeight = windowHeight;
	this.WindowWidth  = windowWidth;

	var newWidth = null;
	if (this.originalDimensions.width.toString().indexOf('%') > -1) {
		var calcWidth = this.calculatePercentWidth();
		if (calcWidth != this.width) 
		{
			newWidth=calcWidth;			
		}
	}

	var newHeight = null;
	if (this.originalDimensions.height.toString().indexOf('%') > -1) {
		var calcHeight = this.calculatePercentHeight();
		if (calcHeight != this.height) 
		{
			newHeight=calcHeight;			
		}
	}

	this.Log.Warning(["Splitter.ResizeHandler . Calculated width[%d] height[%d] ID [%d]", newWidth,newHeight, this.ID]);

	this.Resize(newWidth, newHeight)	
	
	this.lastResize = new Date();
	
	var self = this;
	
	this.Log.Warning(["Splitter.HandleResize real resize done for [%d]ms, ID[%d]", new Date() - startTime,this.ID])
	
	var t = function () {
		if (self.pendingResize)	self.HandleResize();		
	}
	
	var endTime = new Date();
	this.Log.Warning(["Splitter.HandleResize done for [%d]ms, ID[%d]", endTime - startTime,this.ID])
	setTimeout(t,200);
}

MdSplitter.prototype.setSplitterSize = function ()
{
	
	this.Log.Debug(["Splitter.setSplitterSize . ID[%d], real Size [%d]", this.ID, this.box.GetOuterWidth(this.GetContainerElement())]);
	var parentDimensions;
	
	if (this.arePanesFixedSize() && !this.containsInitialFreeSizedPanes())
	{

		/*
		 * This is the case where the splitter size is in % or "",
		 * but all panes are fixed sized (in px).
		 * 
		 * In this case we are getting the size in px from all panes and splt bars
		 * and applying it to the splitter object, overwriting its original size.
		 * 
		 */
		var panesSize     = this.getPanesVarSize()
		var splitBarsSize = this.getSplitBarsSize();
		var bordersSize   = this.getBordersSize();
		var newSize 	  = panesSize + splitBarsSize + bordersSize;
		
		this.Log.Debug(["Splitter.setSplitterSize Reset the splitter size to[%d], panesSize[%d], splitBarsSize[%d], bordersSize[%d] ID[%d]", newSize, panesSize, splitBarsSize, bordersSize, this.ID]);
		
		if (this.IsVertical())
		{
			this.changeOriginalWidth(newSize);
			this.setContainerOuterWidth(newSize);
		}
		else
		{
			this.changeOriginalHeight(newSize);
			this.setContainerOuterHeight(newSize);	
			
		}
	}

	if (this.originalDimensions.width.toString().indexOf('%') > -1) 
	{
	
		var absoluteWidth = this.calculatePercentWidth(); 

		this.Log.Debug(["Splitter.setSplitterSize Recalculated width [%d], original width[%d], ID[%d]", absoluteWidth, this.originalDimensions.width, this.ID]);
		
		this.setContainerInnerWidth(absoluteWidth);
		
		if (!this.IsVertical()) {
		
			var panes = this.GetPanes();
			var splitterInnerWidth = this.GetInnerWidth();
			for (var i=0; i < panes.length; i ++)
			{
				var oPane = panes[i];
				
				panes[i].SetWidth(splitterInnerWidth);
			}
		}
	} 

	if (this.originalDimensions.height.toString().indexOf('%') > -1) 
	{		
		
		var absoluteHeight = this.calculatePercentHeight();  

		this.Log.Debug(["Splitter.setSplitterSize Recalculated height [%d], original height[%d], ID[%d]", absoluteHeight, this.originalDimensions.height, this.ID]);		
		this.setContainerOuterHeight(absoluteHeight);
		if (this.IsVertical()) {
			var panes = this.GetPanes();
			var splitterInnerHeight = this.GetInnerHeight();
			for (var i=0; i < panes.length; i ++)
			{
				var oPane = panes[i];
				
				panes[i].SetHeight(splitterInnerHeight);
			}
		}
	}
	
}

//RSPL-7528
MdSplitter.prototype.fixSplitterActualSize = function ()
{
	if (this.originalDimensions.height.toString().indexOf('%') == -1) return;
	
	var containerElement = this.GetContainerElement();
	if (parseInt(containerElement.style.height) == this.height) return;
	this.setContainerOuterHeight(this.height);
}

MdSplitter.prototype.calculatePercentWidth = function (pcWidth)
{
	return this.calculatePercentSize(pcWidth, null).width;
}

MdSplitter.prototype.calculatePercentHeight = function (pcHeight)
{
	return this.calculatePercentSize(null, pcHeight).height;
}

MdSplitter.prototype.calculatePercentSize = function (pcWidth, pcHeight)
{

	if (!pcWidth)
	{
		pcWidth = this.originalDimensions.width;
	}

	if (!pcHeight)
	{
		pcHeight = this.originalDimensions.height;
	}

	var containerElement = this.getWrapperElement();
	
	containerElement.style.display = "none";
	
	// in IE the size is not real if there are iframes ..
	for (var i=0; i < this.panes.length; i ++)
	{
		this.panes[i].hideContent();		
	}
	
	// create a temp table and check its width
	var tempElement = document.createElement('DIV');
	
	tempElement.style.height = pcHeight;
	tempElement.style.width = pcWidth;
	
	tempElement = containerElement.parentNode.appendChild(tempElement);
	
	var newHeight = this.box.GetOuterHeight(tempElement);
	var newWidth = this.box.GetOuterWidth(tempElement);
	//tempElement.style.border="1px solid red";

	tempElement.parentNode.removeChild(tempElement);
	
	for (var i=0; i < this.panes.length; i ++)
	{
		this.panes[i].showContent();		
	}

	containerElement.style.display = "";	
	var borderDiff = 2 * this.borderSize;
	
	var calcHeight = newHeight - borderDiff - this.heightOffset;
	var calcWidth = newWidth - borderDiff;
	 
	return {
			 width  : calcWidth,
			 height : calcHeight
		   };
}

MdSplitter.prototype.setPanesSize = function ()
{
	var panes = this.GetPanes();
	
	this.Log.Debug(["Splitter.setPanesSize . ID[%d]", this.ID]);
	
	/*
	 *  set the size of the panes that is dependant from the splitter - e.g. the nonvariable size
	 */
	var arePanesPercentSize = this.arePanesPercenSize();

	for (var i=0; i < panes.length; i ++)
	{
		var oPane = panes[i];
		if (oPane.IsPercentSize())
		{
			var panesSize = (this.IsVertical()) ? this.getPanesAvailWidth() : this.getPanesAvailHeight() ;
			var originalSize = (this.IsVertical()) ? oPane.originalDimensions.width : oPane.originalDimensions.height ;
			var paneSize = parseInt(originalSize) * panesSize / 100;
			paneSize = parseInt(paneSize);
			oPane.setVarSize(paneSize);
			oPane.callMdResize();
		}
	}
		
	/*
	 * 
	 * Here we are sure that the splitter contains:
	 *  o only fixed panes
	 *  o only percent panes
	 *  o or only fixed and freesized panes
	 *  
	 *  Also the spliiter size is defined in PX.
	 * 
	 */
	// calculate the size of each free-sized pane
	if (this.containsFreeSizedPanes())
	{
		this.Log.Debug(["Splitter.setPanesSize Detected free sized panes splID[%d]", this.ID]);

		var splitterSize = (this.IsVertical()) ? this.width : this.height ;
		var splitBarsSize = this.getSplitBarsSize();

		var bordersSize = this.getBordersSize();

		// get the available size
		var availFreeSize = (this.IsVertical()) ? this.getPanesAvailWidth() : this.getPanesAvailHeight() ;

		// get the panes count
		var panes = this.GetPanes();
		var freeSizedPanesCount = 0;
		for (var i=0; i < panes.length; i ++)
		{
			if (panes[i].IsFixedSize())
			{
				availFreeSize -= panes[i].getVarSize();
			} 
			else
			{
				if (panes[i].IsLocked() || (panes[i].initiallyCollapsed && panes[i].expandedSize > 0)) continue;
				freeSizedPanesCount ++;
			}
		}

		// calculate the size per pane
		var sizeToApply = availFreeSize / freeSizedPanesCount;
		sizeToApply = parseInt(sizeToApply);

		this.Log.Debug(["Splitter.setPanesSize Found [%d] free sized panes. Avail free size[%d], size per pane[%d], splitterSize[%d], splitBarsSize[%d], panesBorderSize[%d], splID[%d]", freeSizedPanesCount, availFreeSize, sizeToApply, splitterSize, splitBarsSize, this.panesBorderSize,this.ID]);	
		var freeSizedPanes = this.getFreeSizedPanes();
		
		
		for (var i=0; i < freeSizedPanes.length; i ++)
		{
			if (freeSizedPanes[i].IsLocked() || (freeSizedPanes[i].initiallyCollapsed && freeSizedPanes[i].expandedSize > 0)) continue;
			freeSizedPanes[i].setVarSize(sizeToApply);
			freeSizedPanes[i].callMdResize();
		}
	}
}

MdSplitter.prototype.getFreeSizedPanes = function () 
{
	var panes = this.GetPanes();
	var freeSizedPanes = [];
	for (var i=0; i < panes.length; i ++)
	{
		if (panes[i].IsFreeSize()) {
			freeSizedPanes[freeSizedPanes.length] = panes[i];
		}		
	}

	return freeSizedPanes;
}

MdSplitter.prototype.getInitialFreeSizedPanes = function () 
{
	var panes = this.GetPanes();
	var freeSizedPanes = [];
	for (var i=0; i < panes.length; i ++)
	{
		if (panes[i].IsInitialFreeSize()) {
			freeSizedPanes[freeSizedPanes.length] = panes[i];
		}		
	}

	return freeSizedPanes;
}


MdSplitter.prototype.getPanesVarSize = function () 
{
	var panes = this.GetPanes();
	var size = 0;
	for (var i=0; i < panes.length; i ++)
	{
		size += panes[i].getVarSize();
	}

	return size;
}

MdSplitter.prototype.getPanesAvailWidth = function () 
{

	var width = this.GetWidth() - this.getBordersSize();
	if (this.IsVertical()) 
	{
		width -= this.getSplitBarsSize();
	}
	return width;
}

MdSplitter.prototype.getPanesAvailHeight = function () 
{
	var height = this.GetHeight() - this.getBordersSize();
	if (!this.IsVertical()) 
	{
		height -= this.getSplitBarsSize();
	}
	return height;
}

MdSplitter.prototype.getPanesBordersSize = function () 
{
	var activePanesCount = 0;
	
	for (var i=0; i < this.panes.length; i ++)
	{
		if (!this.panes[i].IsCollapsed())
		{
			activePanesCount ++;
		}
	}

	return (activePanesCount -1) * this.panesBorderSize;
}

MdSplitter.prototype.getBordersSize = function () 
{
	var activePanesCount = 0;
	
	for (var i=0; i < this.panes.length; i ++)
	{
		if (!this.panes[i].IsCollapsed())
		{
			activePanesCount ++;
		}
	}
	
	return ( Math.max(activePanesCount + this.splitBars.length - 1, 0)) * this.panesBorderSize + this.getBordersDiff();
}

MdSplitter.prototype.getBordersDiff = function () 
{
	var diff = 0;//(document.all) ? 2 * this.borderSize : 0;
	return diff;
}


MdSplitter.prototype.getSplitBarsSize = function () 
{
	var splitBarsSize = 0;

	if (this.splitBarsSizeCalculated) return this.splitBarsSize;
	
	if (this.splitBars.length > 0) 
	{
		var size = 0;
		
		if (typeof(this.splitBarsSize) != "undefined") {
			size = parseInt(this.splitBarsSize);			
		} else {
			var splitBar = this.GetSplitBarByIndex(0);
			
			var element = splitBar.GetContainerElement();
			
			// create an temp element and apply the same classes to see what is the real sizse of the splitbar
			var tmpElement = document.createElement('DIV');
			
			tmpElement.className = this.GetContainerElement().className;
			
			tmpElement.style.position = "absolute";
			tmpElement.style.top  = -1000;
			tmpElement.style.left = -1000;
			
			tmpElement.style.width  = 500;
			tmpElement.style.height = 500;
			
			var tmpElement2 = document.createElement('DIV');
			tmpElement2.className = element.className;
			tmpElement2.style.backgroundColor= "red";
			
			tmpElement.appendChild(tmpElement2);
			
			tmpElement = document.body.appendChild(tmpElement);
			
			size = (this.IsVertical()) ? this.box.GetOuterWidth(tmpElement2) : this.box.GetOuterHeight(tmpElement2);

			size -= 2 * this.panesBorderSize;
			
			size = Math.max(size, 0);
			
			tmpElement.parentNode.removeChild(tmpElement);
		}
		
		splitBarsSize = this.splitBars.length * size;
	}
	
	this.splitBarsSizeCalculated = true;

	this.splitBarsSize = splitBarsSize;

	return splitBarsSize;
}

MdSplitter.prototype.getAvailIncreaseDelta = function (paneIndex, direction) 
{
	var maxDelta = 0;
	switch (this.resizeMode) 
	{

		/*	[|| ->|||]
			        +
		*/
		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.END_PANE :
			
			var endPane = (direction == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) ? this.GetEndPane() : this.GetStartPane();
			
			maxDelta = endPane.getAvailIncreaseDelta();
			
			break;

		/*	[|| ->|||]
			       +++
		*/
		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.PROPORTIONAL :
			
			var arrPanes = [];
			if (direction == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) 
			{
				for (var i = paneIndex + 1; i < this.panes.length; i ++) 
				{
					arrPanes[arrPanes.length] = this.GetPaneByIndex(i);
				}
			} 
			else 
			{
				for (var i = paneIndex - 1; i >= 0; i --) 
				{
					arrPanes[arrPanes.length] = this.GetPaneByIndex(i);
				}
			}
			
			// the next panes will increase their size when the pane size is decreased
			for (var i = 0; i < arrPanes.length; i ++) 
			{

				var oPane = arrPanes[i];
				
				maxDelta += oPane.getAvailIncreaseDelta();
			}
			
			break;

		/*	[|| ->|||]
			       +    
		*/
		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.ADJACENT_PANE :
		default :

			var adjacentPane = this.getAvailAdjacentPane(paneIndex, direction);

			if (adjacentPane == null) return 0;
			
			this.Log.Debug(["Splitter.getAvailIncreaseDelta: GotAdjacentPane[%d]", adjacentPane.ID]);
			maxDelta += adjacentPane.getAvailIncreaseDelta();
	}

	maxDelta = Math.max(maxDelta, 0);// in case of some negative values
	this.Log.Debug(["Splitter.getAvailIncreaseDelta: delta[%d]", maxDelta]);
	return maxDelta;
}

MdSplitter.prototype.getAvailAdjacentPane = function (paneIndex, direction) 
{

	if ((this.panes.length - 1 )== paneIndex) 
	{
		this.Log.Debug(["Splitter.getAvailAdjacentPane: Detected End Pane Index[%d]", paneIndex]);
		direction = MdSplitterNamespace.Md_SPLITTER_DIRECTION.Backward;
	} 
	else if (paneIndex == 0) 
	{
		this.Log.Debug(["Splitter.getAvailAdjacentPane: Detected Start Pane Index[%d]", paneIndex]);
		direction = MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward;
	}

	
	var adjacentPaneIndexDiff 	= (direction == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) ? 1 : -1;
	var adjacentPaneIndex  		= paneIndex + adjacentPaneIndexDiff;
	var adjacentPaneObj = null
	
	do 
	{
		adjacentPaneObj = this.GetPaneByIndex(adjacentPaneIndex);
		
		if (adjacentPaneObj == null) 
		{
			return null;
		}

		adjacentPaneIndex += adjacentPaneIndexDiff;

	} while (adjacentPaneObj.IsCollapsed() || adjacentPaneObj.IsLocked());

	return adjacentPaneObj;
}

MdSplitter.prototype.getAvailDecreaseDelta = function (paneIndex, direction) 
{

	var maxDelta = 0;
	switch (this.resizeMode) 
	{

		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.END_PANE :

			/*	[||<- |||]
				        +
			*/
			// the end pane will be expanded when the pane size is decreased
			var endPane = (direction == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) ? this.GetEndPane() : this.GetStartPane();
			
			maxDelta = endPane.getAvailDecreaseDelta();
			
			break;

		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.PROPORTIONAL :
			
			/*	[||<- |||]
				      +++
			*/
			
			this.Log.Debug(['paneIndex[%d], panesLength[%d]',paneIndex,this.panes.length])
			
			var arrPanes = [];
			if (direction == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) 
			{
				for (var i = paneIndex + 1; i < this.panes.length; i ++) 
				{
					arrPanes[arrPanes.length] = this.GetPaneByIndex(i);
				}
			} 
			else 
			{
				for (var i = paneIndex - 1; i >= 0; i --) 
				{
					arrPanes[arrPanes.length] = this.GetPaneByIndex(i);
				}
			}
			
			// the next panes will increase their size when the pane size is decreased
			for (var i = 0; i < arrPanes.length; i ++) 
			{
				var oPane = arrPanes[i];
				
				maxDelta += oPane.getAvailDecreaseDelta();
			}
			break;

		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.ADJACENT_PANE :
		default :
			/*	[||<- |||]
				        +
			*/
			// the next pane will be resized
			
			var adjacentPane = this.getAvailAdjacentPane(paneIndex, direction);
			if (adjacentPane == null) return 0;
			
			this.Log.Debug(["Splitter.getAvailDecreaseDelta: Found AdjacentPane[%d] for paneIndex[%d]", adjacentPane.ID, paneIndex]);
			
			maxDelta = adjacentPane.getAvailDecreaseDelta();
	}

	maxDelta = Math.max(maxDelta, 0);
	this.Log.Debug(['Splitter.getAvailDecreaseDelta: maxDelta[%d]', maxDelta]);

	return maxDelta;
}

MdSplitter.prototype.collapsePane = function (targetPane, direction)
{
	
	if (!targetPane.initialCollapseMode && !targetPane.RaiseEvent('OnClientBeforePaneCollapse', {paneObj : targetPane}))
	{
		return false;		
	}

	this.isCollapseMode = true;
	if (typeof(direction) == 'undefined')
	{
		direction = MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward
	}

	var collapseDelta = targetPane.getVarSize();

	if (collapseDelta > 0) 
	{
		collapseDelta += this.panesBorderSize; 
	}
	
	this.Log.Debug(["Splitter.collapsePane delta[%d], Fwd[%s]", collapseDelta,(direction == MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward) ]);
	
	var availDelta = this.getAvailIncreaseDelta(targetPane.Index, direction);
	
	if (availDelta < collapseDelta) 
	{
	
		this.Log.Warning(['Splitter.collapsePane Can not collapse pane. No enough delta. CollapseDelta[%d], availDelta[%d], targetPane[%d]', collapseDelta, availDelta, targetPane.ID]);
		this.isCollapseMode = false;
		return false;
	}
	
	collapseDelta *= -1;
	
	targetPane.collapse(direction);
	targetPane.Resize(collapseDelta, direction);
	
	if (!targetPane.initialCollapseMode) 
	{
		targetPane.RaiseEvent('OnClientPaneCollapsed', {paneObj : targetPane});
	}
	
	this.isCollapseMode = false;
	return true;
	
} 

MdSplitter.prototype.expandPane = function (targetPane, direction)
{
	
	if (!targetPane.RaiseEvent('OnClientBeforePaneExpand', {paneObj : targetPane}))
	{
		return false;		
	}
	
	this.isExpandMode = true;
	if (typeof(direction) == 'undefined')
	{
		direction = MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward
	}

	var expandDelta = targetPane.expandedSize;
	this.Log.Debug(["Splitter.expandPane paneId[%d], delta [%d]", targetPane.ID, expandDelta]);

	expandDelta += this.panesBorderSize;

	var availDelta = this.getAvailDecreaseDelta(targetPane.Index, direction);

	if (availDelta <= 0 )  
	{
		this.Log.Warning(['No avail delta . availDelta[%d], expandDelta[%d]', availDelta, expandDelta]);
		this.isExpandMode = false;
		return false;
	}

	var minExpandDelta = targetPane.getVarMinSize();
	
	if (minExpandDelta > availDelta) 
	{
		this.Log.Warning(["Splitter.expandPane No enough avail delta paneID[%d], minExpandDelta[%d], availDelta[%d]", targetPane.ID, minExpandDelta, availDelta]);
		this.isExpandMode = false;
		return false;
	}

	var deltaToApply = Math.min(availDelta, expandDelta );

	this.Log.Debug(["Splitter.expandPane Applying paneId[%d], expandedPaneSize[%d], availDelta[%d], delta [%d]", targetPane.ID, targetPane.expandedSize, availDelta, deltaToApply]);
	
	targetPane.show(); // show it in order to set the size correctly
	targetPane.Resize(deltaToApply, direction);
	
	deltaToApply -= this.panesBorderSize;

	targetPane.expand(deltaToApply);
	targetPane.RaiseEvent('OnClientPaneExpanded', {paneObj : targetPane});
	this.isExpandMode = false;
	return true;
}

MdSplitter.prototype.resizePanes = function (delta, targetPane, resizeDirection) 
{
	
	this.Log.Debug(["Splitter.resizePanes delta[%d]", delta])
	if (typeof(resizeDirection) == 'undefined')
	{
		resizeDirection = MdSplitterNamespace.Md_SPLITTER_DIRECTION.Forward;
	}	

	/**
		According to the resize mode - resize the panes
	*/
	switch (this.resizeMode) 
	{

		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.END_PANE :
			this.resizeEndPane(delta, targetPane, resizeDirection);
			break;

		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.PROPORTIONAL :
			this.resizeProportional(delta, targetPane, resizeDirection);
			break;

		case MdSplitterNamespace.Md_SPLITTER_RESIZE_MODE.ADJACENT_PANE :
		default :
			this.resizeAdjacentPane(delta, targetPane, resizeDirection);
	}
}

MdSplitter.prototype.changeOriginalWidth = function (newWidth)
{
	this.originalDimensions.width = newWidth;
}

MdSplitter.prototype.changeOriginalHeight = function (newHeight)
{
	this.originalDimensions.height = newHeight;
}


// a helper method to avoid repeating logic
MdSplitter.prototype.getMinMaxSize = function (startPaneIndex, endPaneIndex, isMin, isWidth) 
{
	if (!startPaneIndex) 
	{
		startPaneIndex = 0;
	}
	
	if (!endPaneIndex)
	{
		endPaneIndex = this.panes.length;
	}

	startPaneIndex = Math.max(0, startPaneIndex);
	endPaneIndex   = Math.min(endPaneIndex, this.panes.length);

	var getSizeMethod   = (isWidth) ? "GetWidth" : "GetHeight";
	
	var getMinMaxMethod = (isMin) ? "GetMin" : "GetMax";
	getMinMaxMethod += (isWidth) ? "Width" : "Height"

	var calculatedSize = this.getSplitBarsSize() + this.getBordersSize();
	for (var i=startPaneIndex; i < endPaneIndex; i++) 
	{
		var oPane = this.GetPaneByIndex(i);
		calculatedSize += (oPane.IsLocked()) ? oPane[getSizeMethod]() : oPane[getMinMaxMethod]();
	}

	return calculatedSize;
}

// is the splitter in a hidden container
MdSplitter.prototype.isDisplayed = function () 
{
	return (this.GetContainerElement().offsetWidth != 0);
}

MdSplitter.prototype.calculateInitialSize = function () 
{
	if (this.initialSizeSet) return;
	if (!this.isDisplayed()) return;
	
	this.setSplitterSize();
	this.setPanesSize();
	
	// sometimes when use the heightOffset the splitter is not able to DECREASE its height 
	// (RSPL-7528)
	this.fixSplitterActualSize();
	
	if (!this.visibleDuringInit)
	{
		var containerElement = this.GetContainerElement();
		containerElement.style.visibility = "visible";
	}
	this.initialSizeSet = true;
}

//BEGIN_ATLAS_NOTIFY
if (typeof(Sys) != "undefined")
{
	if (Sys.Application != null && Sys.Application.notifyScriptLoaded != null)
	{
		Sys.Application.notifyScriptLoaded();
	}
}
//END_ATLAS_NOTIFY