Newer
Older
lostmynuts / shared / js / Engine / Utils / ScrollWindow.js
// WEBGL matches: commit 6a91aa9d4f89df66e2e3fa1adb784f72af5138df, Feb 1st 2019

Engine.ScrollWindow = class extends Engine.Drawable 
{
	constructor(scrollButton /*string*/, scrollBarBG /*string*/, scrollBarScroller /*string*/, dotsOnBar /*bool*/)
	{
		super();

		if (scrollButton === undefined) scrollButton = "Chat_ScrollButton";
		if (scrollBarBG === undefined) scrollBarBG = "ScrollBG";
		if (scrollBarScroller === undefined) scrollBarScroller = "Button_TinyDarkGray";
		if (dotsOnBar === undefined) dotsOnBar = false;

		this.scrollPane = new Engine.ScrollPaneVHRecycling();
		this.scrollBar = new Engine.ScrollBar();
		this.scrollMask = new PIXI.Graphics();
		this.scrollBox = new PIXI.Graphics();
		this.displayItemSource = null;
		this.displayItemReturn = null;
		this.layoutWidth = 0;
		this.layoutHeight = 0;
		this.enabled = false;
		this.headerIndices = [];
		this.scrollX = null;
		this.scrollY = null;
		this.scrollHeight = null;
		this.scrollWidth = null;
		this.scrollButtonSpacing = null;
		this.scrollScrollerHeight = null;
		
		this.scrollBar.setScrollPane(this.scrollPane);
		this.scrollBar.init(scrollButton, scrollBarBG, scrollBarScroller);
		
		if (scrollBarScroller == "Button_TinyDarkGray" || dotsOnBar)
		{
			this.scrollBar.setScrollerIcon("Icon_ScrollBar");
		}
		
		//this.mask.events.onScroll.addListener(this, this.globalMouseWheel);
		
		this.onActivated = (active) => { this.setEvents(active); } 
		this.addChild(this.scrollMask);
		this.addChild(this.scrollPane);
		this.addChild(this.scrollBar);
		
		this.scrollPane.mask = this.scrollMask;

        this.scrollBar.scrollerMouseFlickEnabled(false);
	}

	//get width() { return this._width; }
	//set width(value) { this._width = value; }

	//get height() { return this._height; }
	//set height(value) { this._height = value; }

	get itemCount()
	{
		return this.scrollPane.items.length;
	}

	get horz()
	{
		return this.scrollPane.horz;
	}
	set horz(value)
	{
		this.scrollPane.horz = value;
	}

	get enabled()
	{
		return this._enabled;
	}
	set enabled(value)
	{
		if (this._enabled != value)
		{
			this._enabled = value;

			if (this._enabled)
			{
				Engine.Mouse.addEventListener('mousedown', this, this.globalMouseDown);
				Engine.Mouse.addEventListener('mousewheel', this, this.globalMouseWheel);
				//Engine.Mouse.events.on('mouseflick', this, this.globalMouseFlick } );
			}
			else
			{
				Engine.Mouse.removeEventListener('mousedown', this);//, this.globalMouseDown);
				Engine.Mouse.removeEventListener('mousewheel', this);//, this.globalMouseWheel);
				//Engine.Mouse.removeEventListener('mouseflick', this.globalMouseFlick } );
			}
		}
	}

	globalMouseFlick(e /*Vector2*/)
	{
		var bounds = this.scrollBox.getBounds();
		bounds.x = this.screenX;
		bounds.y = this.screenY;
		//bounds.width = this.scrollPane.width;//this.layoutWidth - this.scrollBar.width;
		//bounds.height = this.scrollPane.height;//this.layoutHeight;

		if (bounds.contains(Engine.Mouse.position.x, Engine.Mouse.position.y)) this.scrollBar.flicked(null, e);
	}

	globalMouseDown(e /*Vector2*/)
	{
		var bounds = this.scrollBox.getBounds();
		bounds.x = this.screenX;
		bounds.y = this.screenY;
		//bounds.width = this.layoutWidth;//this.layoutWidth - this.scrollBar.width;
		//bounds.height = this.layoutHeight;//this.layoutHeight;

		if (bounds.contains(Engine.Mouse.position.x, Engine.Mouse.position.y))
		{
			this.scrollBar.beginTouchScroll(null);
		} 
	}

	globalMouseWheel(velocity)
	{
		var bounds = this.getBounds();
		if (this.enabled && this.scrollBar.allowScroll && bounds.contains(Engine.Mouse.position.x, Engine.Mouse.position.y))
		{
			this.scrollBar.mouseWheel(velocity / 10);
		}
	}

	setEvents(active)
	{
		this.enabled = active;
	}

	scrollPixelAmount(pixels /*int*/)
	{
		var percentChange = 0;
		if (this.scrollPane.getScrollHeight() > 0)
		{
			percentChange = pixels / this.scrollPane.getScrollHeight();
		}
		this.scrollPane.scrollToPercent(this.scrollPane.scrollPercent + percentChange);
	}

	scrollByGamepad(velocity /*float*/)
	{
		if (this.enabled && this.scrollBar.allowScroll)
		{
			this.scrollBar.mouseWheel(velocity / 20);
		}
	}

	init()
	{
		this.layout(this.layoutWidth, this.layoutHeight);
	}

	addHeader(data /*TData*/, itemWidth /*int*/, itemHeight /*int*/)
	{
		this.headerIndices.push(this.scrollPane.items.length);
		var item = this.addItem(data, itemWidth, itemHeight);
		return item;
	}

	addItem(data /*TData*/, itemWidth /*int*/, itemHeight /*int*/)
	{
		var item = new Engine.RecycledScrollItem(data, itemWidth, itemHeight, (data) => { return this.getItem(data); }, (item) => { this.returnItem(item); } );
		this.scrollPane.addItem(item);
		return item;
	}

	clear()
	{
		this.headerIndices = [];
		this.scrollPane.clearPane();
	}

	removeItem(itemDef /*TData*/)
	{
		var item = null;
		for (var i = 0; i < this.scrollPane.items.length; i++)
		{
			if (this.scrollPane.items[i].data == itemDef)
			{
				item = this.scrollPane.items[i];
				break;
			}
		}
		
		if (item != null) this.removeItemByClip(item);
	}

	removeItemByClip(item /*RecycledScrollItem<TData,TClip>*/)
	{
		var items = this.scrollPane.items.slice();
		items.remove(item);
		this.scrollPane.clearPane();
		for (var i = 0; i < items.length; i++) this.scrollPane.addItem(items[i]);

		if (item.currentDrawable)
		{
			this.returnItem(item);
			item.currentDrawable = null;
		}
	}

	moveItemUp(itemDef /*TData*/)
	{
		var items = this.scrollPane.items;
		for (let i = 1; i < items.length; i++)
		{
			if (items[i].data == itemDef)
			{
				const tmp = items[i - 1];
				items[i - 1] = items[i];
				items[i] = tmp;
				break;
			}
		}
		this.scrollPane.updateItemPositions();
	}

	moveItemDown(itemDef /*TData*/)
	{
		var items = this.scrollPane.items;
		for (let i = 0; i < items.length - 1; i++)
		{
			if (items[i].data == itemDef)
			{
				const tmp = items[i + 1];
				items[i + 1] = items[i];
				items[i] = tmp;
				break;
			}
		}
		this.scrollPane.updateItemPositions();
	}

	setItems(data /*List<TData>*/, itemWidth /*int*/, itemHeight /*int*/)
	{
		this.scrollPane.clearPane();
		for(var i = 0; i < data.length; i++)
		{
			var dataItem = data[i];
			this.scrollPane.addItem(new Engine.RecycledScrollItem(dataItem, itemWidth, itemHeight, (data) => { return this.getItem(data); }, (item) => { this.returnItem(item); } ));
		}
		this.scrollBar.visible = (this.scrollPane.getScrollHeight() > this.layoutHeight);
	}

	setScrollPercent(percent /*float*/)
	{
		this.scrollPane.setScrollPercent(percent);
	}

	getScrollPercent()
	{
		return this.scrollPane.scrollPercent;
	}

	getItem(data /*TData*/)
	{
		if (this.displayItemSource != null) return this.displayItemSource(data);
		return null;
	}

	returnItem(returnItem /*TClip*/)
	{
		if (this.displayItemReturn != null) this.displayItemReturn(returnItem);
	}

	layout(width /*int*/, height /*int*/, numColumns /*int*/, itemSpacing /*Vector2*/, includeScrollBarInWidth)
	{
		if (numColumns === undefined) numColumns = 1;
		if (itemSpacing === undefined) itemSpacing = new Vector2();
		if (includeScrollBarInWidth === undefined) includeScrollBarInWidth = true;

		this.layoutHeight = height;
		this.layoutWidth = width;

		this.setScrollBarRect(this.scrollX, this.scrollY, this.scrollWidth, this.scrollHeight, this.scrollButtonSpacing);
		
        var scrollbarWidth = 0;
		if (this.hasScrollBar())
		{
			// include scrollbar means scrollbar is within the width
			this.layoutWidth = width + (includeScrollBarInWidth ? 0 : this.scrollBar.width);
            scrollbarWidth = includeScrollBarInWidth ? Math.trunc(this.scrollBar.width) : 0;
			this.scrollBar.x = this.layoutWidth - this.scrollBar.width;
		}

		this.scrollMask.x = 0;
		this.scrollMask.y = 0;
        this.scrollMask.clear();
        this.scrollMask.beginFill(0xFFFFFF, 0.5);
        this.scrollMask.drawRect(0, 0, width - scrollbarWidth, height);

		this.scrollBox.x = 0;
		this.scrollBox.y = 0;
        this.scrollBox.clear();
        this.scrollBox.beginFill(0xFFFFFF, 0);
        this.scrollBox.drawRect(0, 0, this.hasScrollBar() ? this.scrollBar.x : this.layoutWidth, height);

		if (!this.horz) this.scrollPane.init(height, numColumns);
		else this.scrollPane.init(width, numColumns, true);
		this.scrollPane.updateItemPositions(itemSpacing.x, itemSpacing.y, this.headerIndices);
		this.scrollPane.y = 0;	
	}

	setScrollBarRect(x, y, width, height, buttonSpacing, scrollerHeight)
	{
		if (x === undefined) x = null;
		if (y === undefined) y = null;
		if (width === undefined) width = null;
		if (height === undefined) height = null;
		if (buttonSpacing === undefined) buttonSpacing = null;
		if (scrollerHeight === undefined) scrollerHeight = null;

		this.scrollX = x != null ? x : this.scrollX;
		this.scrollY = y != null ? y : this.scrollY;
		this.scrollWidth = width != null ? width : this.scrollWidth;
		this.scrollHeight = height != null ? height : this.scrollHeight;
		this.scrollButtonSpacing = buttonSpacing != null ? buttonSpacing : 0;
		this.scrollScrollerHeight = scrollerHeight != null ? scrollerHeight : 0;

		this.scrollBar.setHeight(this.scrollHeight != null ? this.scrollHeight : this.layoutHeight, width != null ? width : 0, buttonSpacing != null ? buttonSpacing : 0, this.scrollScrollerHeight != null ? this.scrollScrollerHeight : 0);
		this.scrollBar.x = this.scrollX != null ? this.scrollX : this.layoutWidth - this.scrollBar.Width;
		this.scrollBar.y = this.scrollY != null ? this.scrollY : 0;
	}

	removeScrollBar()
	{
		this.removeChild(this.scrollBar);
	}

	addScrollBar()
	{
		this.addChild(this.scrollBar);
	}

	hasScrollBar()
	{
		return this.scrollBar.hasParent;
	}
}