﻿
/*************************************************************************
*
* ADOBE CONFIDENTIAL
* ___________________
*
*  Copyright 2008 Adobe Systems Incorporated
*  All Rights Reserved.
*
* NOTICE:  All information contained herein is, and remains
* the property of Adobe Systems Incorporated and its suppliers,
* if any.  The intellectual and technical concepts contained
* herein are proprietary to Adobe Systems Incorporated and its
* suppliers and may be covered by U.S. and Foreign Patents,
* patents in process, and are protected by trade secret or copyright law.
* Dissemination of this information or reproduction of this material
* is strictly forbidden unless prior written permission is obtained
* from Adobe Systems Incorporated.
*
* $DateTime: 2008/04/10 13:35:00 $
*
* Adobe Output Module 2.0
*
* MediaGallery Originally Written by Quality Process Incorporated, Enhanced by
* Adobe System China. Contact Sheet written by Adobe System China.
* 
*
**************************************************************************/

AOM.CustomScrollbar = function(scroll) {
	this.initialize(scroll);
}

AOM.CustomScrollbar.prototype.initialize = function(scroll) {
	if (scroll == undefined)  {
		return false;
	}

	scroll.value = AOM.MINVALUE;
	scroll.minvalue = AOM.MINVALUE;
	scroll.maxvalue = AOM.MINVALUE;
	scroll.stepdelta = AOM.STEPDELTA;
	scroll.wheeldelta = AOM.WHEELDELTA_WIN;
	scroll.jumpdelta = 0;
	
	scroll.scrollSizeValue = 0;
	scroll.arrowSizeValue = 0;
	scroll.indicatorSizeValue = 0;
	scroll.indicatorLocationValue = 0;
	scroll.mouseDown = false;

	//add scroll method
	scroll.recalculate = function() {
		if (this.size.width > this.size.height) {
			this.hasVScroll = false;
		} else {
			this.hasVScroll = true;
		}
	
		this.scrollSizeValue = this.hasVScroll ? this.size.height : this.size.width;

		this.contentSizeValue = this.getContentSizeValue();
		
		this.jumpdelta = AOM.JUMPDELTA * this.scrollSizeValue;
		
		if (File.fs == "Windows") {
			this.wheeldelta = AOM.WHEELDELTA_WIN * this.scrollSizeValue;
		} else {
			this.wheeldelta = AOM.WHEELDELTA_MAC * this.scrollSizeValue;
		}
		
		this.arrowSizeValue = this.getArrowSizeValue();

		this.indicatorSizeValue = this.getIndicatorSizeValue();
		
		this.value = 0;
		
		this.indicatorLocationValue =  this.getIndLocationByValue(this.value); 
	}

	scroll.getContentSizeValue = function() {
		return ( (this.maxvalue - this.minvalue) + this.scrollSizeValue) ;
	}

	scroll.getArrowSizeValue = function() {
		if(this.hasVScroll) {
			return AOM.VSCROLLER_HEIGHT;
		} else {
			return AOM.HSCROLLER_WIDTH;
		}
	}

	scroll.getRealIndicatorSizeValue = function() {
		var indicatorSizeValue = this.scrollSizeValue * (this.scrollSizeValue - 2 * this.arrowSizeValue)
											/ this.contentSizeValue;
											
		return indicatorSizeValue;
	}
	scroll.getIndicatorSizeValue = function() {
		var indicatorSizeValue = this.getRealIndicatorSizeValue();
											
		if (indicatorSizeValue < AOM.MININDICATORSIZE) {
			indicatorSizeValue = AOM.MININDICATORSIZE;
		}
	
		return indicatorSizeValue;
	}

	scroll.getValueByIndLocation = function(indLocation) {
		var value ;
		
		if (this.indicatorSizeValue > AOM.MININDICATORSIZE) {
			value = this.scrollSizeValue * (indLocation - this.arrowSizeValue) / this.indicatorSizeValue;
		} else {
			value = (this.contentSizeValue - this.scrollSizeValue) * (indLocation - this.arrowSizeValue) 
							/ (this.scrollSizeValue - 2 * this.arrowSizeValue - this.indicatorSizeValue);
		}
		
		return value;
	} 

	scroll.getIndLocationByValue = function(value) {
		var indLocation ;
	
		if (this.indicatorSizeValue > AOM.MININDICATORSIZE) {
			indLocation = (this.indicatorSizeValue * value / this.scrollSizeValue) + this.arrowSizeValue;
		} else {
			indLocation = ( (this.scrollSizeValue - 2 * this.arrowSizeValue - this.indicatorSizeValue) * value 
									/ (this.contentSizeValue - this.scrollSizeValue) ) + this.arrowSizeValue;
		}
		
		return indLocation;
	}

	//set scroll arrow dimension
	scroll.getIndicatorSize = function() {
		if (this.hasVScroll) {
			return {width: AOM.VSCROLLER_WIDTH, height: this.indicatorSizeValue};
		} else {
			return {width: this.indicatorSizeValue, height: AOM.HSCROLLER_HEIGHT};
		}
	}

	scroll.getIndicatorLocation = function() {
		if (this.hasVScroll) {
			return {x:0, y: this.indicatorLocationValue};
		} else {
			return {x: this.indicatorLocationValue, y : 0};
		}
	}

	scroll.addEventListener ('mousedown', AOM.CustomScrollbar.doDown, false);
	scroll.addEventListener ('mouseup', AOM.CustomScrollbar.doUp, false);
	scroll.addEventListener('mousemove', AOM.CustomScrollbar.doMove, false);
	scroll.addEventListener('mouseout', AOM.CustomScrollbar.doOut, false);
	scroll.addEventListener('mouseover', AOM.CustomScrollbar.doOver, false);
	
	return true;
}


AOM.CustomScrollbar.getClientValue = function(mouseEvent, hasVScroll) {
	if (hasVScroll) {
		return mouseEvent.clientY;
	} else {
		return mouseEvent.clientX;
	}
}


AOM.CustomScrollbar.keepMoving = function() {
	var scroll = AOM.CustomScrollbar.currentScroll;
	if (scroll == undefined || scroll.mouseDown == false) return;

	var value = scroll.value;
	
	//get current mouse client value
	var mouseClientValue = scroll.oldMouseClientValue;

	//if mouse in up arrow bounds
	if (0 < mouseClientValue && mouseClientValue < scroll.arrowSizeValue) {
		AOM.CustomScrollbar.currentStepCount = AOM.CustomScrollbar.currentStepCount + 1;
				
		value = value  - scroll.stepdelta * AOM.CustomScrollbar.currentStepCount;
		if (value <= scroll.minvalue) value = scroll.minvalue;
		
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
	}

	//if mouse in down arrow bounds
	if ( (scroll.scrollSizeValue - scroll.arrowSizeValue) < mouseClientValue  && mouseClientValue < scroll.scrollSizeValue) {
		AOM.CustomScrollbar.currentStepCount = AOM.CustomScrollbar.currentStepCount + 1;
		value = value + scroll.stepdelta * AOM.CustomScrollbar.currentStepCount;
		if (value >= scroll.maxvalue) value = scroll.maxvalue;
		
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
	}
	
	//if mouse between up arrow and indicator .
	if (scroll.arrowSizeValue < mouseClientValue && mouseClientValue < scroll.indicatorLocationValue) {
		value = value - scroll.jumpdelta;
		if (value <= scroll.minvalue) value = scroll.minvalue;
		
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
	}

	//if mouse between indicator and down arrow
	if ( (scroll.indicatorLocationValue + scroll.indicatorSizeValue) < mouseClientValue 
				&& mouseClientValue < (scroll.scrollSizeValue - scroll.arrowSizeValue) ) {
		
		value = value + scroll.jumpdelta;
		if (value >= scroll.maxvalue) value = scroll.maxvalue;
		
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
	}

	//move scrollgroup
	scroll.onChanging();

	//store current value
	scroll.oldMouseClientValue = mouseClientValue;
	scroll.oldIndicatorLocationValue = scroll.indicatorLocationValue;
	
	if (value > scroll.minvalue && value < scroll.maxvalue) {
		app.scheduleTask("AOM.CustomScrollbar.keepMoving()", 80, false);
	}
}


AOM.CustomScrollbar.doDown = function(event) {
	var scroll = event.target;
	
	scroll.mouseDown = true;
	var mouseClientValue = scroll.hasVScroll ? event.clientY : event.clientX;
	var value = scroll.value;
	
	//if mouse in up arrow bounds
	if (0 < mouseClientValue && mouseClientValue < scroll.arrowSizeValue) {
		value = value  - scroll.stepdelta;
		if (value <= scroll.minvalue) value = scroll.minvalue;
		
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
	}

	//if mouse in down arrow bounds
	if ( (scroll.scrollSizeValue - scroll.arrowSizeValue) < mouseClientValue  && mouseClientValue < scroll.scrollSizeValue) {
		value = value + scroll.stepdelta;
		if (value >= scroll.maxvalue) value = scroll.maxvalue;
		
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
	}
	
	//if mouse between up arrow and indicator .
	if (scroll.arrowSizeValue < mouseClientValue && mouseClientValue < scroll.indicatorLocationValue) {
		value = value - scroll.jumpdelta;
		if (value <= scroll.minvalue) value = scroll.minvalue;
		
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
	}

	//if mouse between indicator and down arrow
	if ( (scroll.indicatorLocationValue + scroll.indicatorSizeValue) < mouseClientValue 
				&& mouseClientValue < (scroll.scrollSizeValue - scroll.arrowSizeValue) ) {
		value = value + scroll.jumpdelta;
		if (value >= scroll.maxvalue) value = scroll.maxvalue;
		
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
	}

	//move scrollgroup
	scroll.onChanging();
	
	//store current value
	scroll.oldMouseClientValue = mouseClientValue;
	scroll.oldIndicatorLocationValue = scroll.indicatorLocationValue;

	//get current scroll, to help implement mouse holder functionality
	AOM.CustomScrollbar.currentScroll = scroll;
	AOM.CustomScrollbar.currentStepCount = 0;
	
	if (value > scroll.minvalue && value < scroll.maxvalue) {
		app.scheduleTask("AOM.CustomScrollbar.keepMoving()", 400, false);
	}
}

AOM.CustomScrollbar.doMove = function(event) {
	var scroll = event.target;
	
	if (scroll.mouseDown == false)  return;

	var mouseClientValue = scroll.hasVScroll ? event.clientY : event.clientX;
	var oldMouseClientValue = scroll.oldMouseClientValue;
	
	//TODO: work around, to fix a bug: on windows mouse move will be triggered  frequently.
	if (File.fs == "Windows") {
		if (Math.abs(mouseClientValue - oldMouseClientValue) < 6) return;
	}
	
	if (scroll.indicatorLocationValue < oldMouseClientValue 
				&& oldMouseClientValue < (scroll.indicatorLocationValue + scroll.indicatorSizeValue) ) {
		
		var oldIndicatorLocationValue = scroll.oldIndicatorLocationValue;
		var indicatorLocationValue ;

		if (mouseClientValue > oldMouseClientValue) {
			//move down
			var maxLocation = scroll.scrollSizeValue - scroll.arrowSizeValue - scroll.indicatorSizeValue;
			indicatorLocationValue = oldIndicatorLocationValue + (mouseClientValue - oldMouseClientValue);
			if (indicatorLocationValue > maxLocation ) {
				indicatorLocationValue = maxLocation;
			}

			scroll.indicatorLocationValue = indicatorLocationValue;
			scroll.value = scroll.getValueByIndLocation(indicatorLocationValue);
		} else {
			//move up
			var minLocation = scroll.arrowSizeValue;
			indicatorLocationValue = oldIndicatorLocationValue +  (mouseClientValue - oldMouseClientValue);
			if (indicatorLocationValue < minLocation) {
				indicatorLocationValue = minLocation;
			}
			scroll.indicatorLocationValue = indicatorLocationValue;
			scroll.value = scroll.getValueByIndLocation(indicatorLocationValue);
		}
	
		scroll.oldMouseClientValue = mouseClientValue;
		scroll.oldIndicatorLocationValue = scroll.indicatorLocationValue;
	
		//move scrollgroup
		scroll.onChanging();
	}
}

AOM.CustomScrollbar.doScrollWheel = function(event) {
	try {
		var scroll = event.target;
		
		//only allow target type is vscrollbar.
		if (scroll.themeType != "Scrollbar") return;
		
		/**
		   *  Using scroll.wheeldelta instead of  event.detail is intended to prevent the unstable value, 
		   *  that is generated by the MouseWheel Interface Program on Mac.
		   */
		var value = scroll.value;
		if (event.detail > 0) {
			value += scroll.wheeldelta; 
		} else {
			value -= scroll.wheeldelta;
		}
		if (value < scroll.minvalue) value = scroll.minvalue;
		if (value > scroll.maxvalue) value = scroll.maxvalue;
		scroll.value = value;
		scroll.indicatorLocationValue = scroll.getIndLocationByValue(value);
		
		//move scrollgroup
		scroll.onChanging();
		
        //Prevent ScriptUI from letting the targeted control handle the OS event
		event.preventDefault();
    } catch (err) {
        //$.writeln("Error in doScrollWheel: " + err + "\nLine: " + err.line);
    }
}

AOM.CustomScrollbar.registerMouseWheel = function(scroll) {
	if (scroll.isRegistedMouseWheel == undefined || scroll.isRegistedMouseWheel == false) {
		scroll.addEventListener('scrollwheel', AOM.CustomScrollbar.doScrollWheel, false);
		scroll.isRegistedMouseWheel = true;
		scroll.active = true;
	}
}

AOM.CustomScrollbar.unregisterMouseWheel = function(scroll) {
	if (scroll.isRegistedMouseWheel) {
		scroll.removeEventListener('scrollwheel', AOM.CustomScrollbar.doScrollWheel, false);
		scroll.isRegistedMouseWheel = false;
	}
}

AOM.CustomScrollbar.doOver = function(event) {
	//register mousewheel
	AOM.CustomScrollbar.registerMouseWheel(event.target);
}

AOM.CustomScrollbar.doOut= function(event) {
	event.target.mouseDown = false;
	AOM.CustomScrollbar.currentScroll = undefined;
	AOM.CustomScrollbar.currentStepCount = 0;
	
	//UnRegister mousewheel
	AOM.CustomScrollbar.unregisterMouseWheel(event.target);
}


AOM.CustomScrollbar.doUp = function(event) {
	event.target.mouseDown = false;
	AOM.CustomScrollbar.currentScroll = undefined;
	AOM.CustomScrollbar.currentStepCount = 0;
}


/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////