/*
	Реализация спецификаций CLDC версии 1.1 (JSR-139), MIDP версии 2.1 (JSR-118)
	и других спецификаций для функционирования компактных приложений на языке
	Java (мидлетов) в среде программного обеспечения Малик Эмулятор.

	Copyright © 2016, 2019 Малик Разработчик

	Это свободная программа: вы можете перераспространять ее и/или изменять
	ее на условиях Меньшей Стандартной общественной лицензии GNU в том виде,
	в каком она была опубликована Фондом свободного программного обеспечения;
	либо версии 3 лицензии, либо (по вашему выбору) любой более поздней версии.

	Эта программа распространяется в надежде, что она будет полезной,
	но БЕЗО ВСЯКИХ ГАРАНТИЙ; даже без неявной гарантии ТОВАРНОГО ВИДА
	или ПРИГОДНОСТИ ДЛЯ ОПРЕДЕЛЕННЫХ ЦЕЛЕЙ. Подробнее см. в Меньшей Стандартной
	общественной лицензии GNU.

	Вы должны были получить копию Меньшей Стандартной общественной лицензии GNU
	вместе с этой программой. Если это не так, см.
	<https://www.gnu.org/licenses/>.
*/


package javax.microedition.lcdui;

public class ScrollBarSystem extends Object
		implements ScrollBarStyle
{
	private static final int SLIDER_MIN_LENGTH = 7;
	private static final int DEFAULT_SIZE = 16;
	private static final int NONE = 0;
	private static final int BACKWARD = 1;
	private static final int TRACK_BACK = 2;
	private static final int SLIDER = 3;
	private static final int TRACK_FORW = 4;
	private static final int FORWARD = 5;
	private static final int HORIZONTAL = 0;
	private static final int VERTICAL = 8;


	private int step;
	private int prev;
	private int focused;
	private int pressed;

	public ScrollBarSystem()
	{
		this.step = 16;
	}

	public ScrollBarSystem(int step)
	{
		this.step = step < 1 ? 1 : step;
	}

	public void paintHorzScrollBar(Graphics render, ScrollBar scrollbar, int length, int width)
	{
		int w;
		int p;
		int a;
		int b;
		int tmp;
		int page;
		int range;
		w = Math.min(DEFAULT_SIZE, width);
		if((range = scrollbar.getRange()) <= 0 || (page = scrollbar.getPage()) <= 0 ||
				range <= page)
		{
			/* рисуем полностью недоступную полосу прокрутки */
			if(length < DEFAULT_SIZE << 1)
			{
				b = length - (a = length / 2);
				render.drawElementOfGUI(10, 2, 2,
						0, 0, a, w);
				render.drawElementOfGUI(10, 3, 2,
						a, 0, b, w);
				return;
			}
			render.drawElementOfGUI(10, 2, 2,
					0, 0, DEFAULT_SIZE, w);
			render.drawElementOfGUI(10, 7, 2,
					DEFAULT_SIZE, 0, length - (DEFAULT_SIZE << 1), w);
			render.drawElementOfGUI(10, 3, 2,
					length - DEFAULT_SIZE, 0, DEFAULT_SIZE, w);
			return;
		}
		p = pressed;
		if(length < SLIDER_MIN_LENGTH + (DEFAULT_SIZE << 1))
		{
			/* рисуем доступную полосу прокрутки без ползунка */
			if(length < DEFAULT_SIZE << 1)
			{
				b = length - (a = length / 2);
				render.drawElementOfGUI(10, 2, p == (HORIZONTAL | BACKWARD) ? 1 : 0,
						0, 0, a, w);
				render.drawElementOfGUI(10, 3, p == (HORIZONTAL | FORWARD) ? 1 : 0,
						a, 0, b, w);
				return;
			}
			render.drawElementOfGUI(10, 2, p == (HORIZONTAL | BACKWARD) ? 1 : 0,
					0, 0, DEFAULT_SIZE, w);
			render.drawElementOfGUI(10, 7, 0,
					DEFAULT_SIZE, 0, length - (DEFAULT_SIZE << 1), w);
			render.drawElementOfGUI(10, 3, p == (HORIZONTAL | FORWARD) ? 1 : 0,
					length - DEFAULT_SIZE, 0, DEFAULT_SIZE, w);
			return;
		}
		/* рисуем доступную полосу прокрутки с ползунком */
		tmp = length - (DEFAULT_SIZE << 1);
		b = (a = ScrollBarPaintHelper.getSliderPosition(scrollbar.getPosition(), page, range, tmp,
				b = ScrollBarPaintHelper.getSliderLength(page, range, tmp, SLIDER_MIN_LENGTH)) +
				DEFAULT_SIZE) + b;
		tmp = length - DEFAULT_SIZE;
		render.drawElementOfGUI(10, 2, p == (HORIZONTAL | BACKWARD) ? 1 : 0,
				0, 0, DEFAULT_SIZE, w);
		render.drawElementOfGUI(10, 6, p == (HORIZONTAL | TRACK_BACK) ? 1 : 0,
				DEFAULT_SIZE, 0, a - DEFAULT_SIZE, w);
		render.drawElementOfGUI(10, 4, p == (HORIZONTAL | SLIDER) ? 1 : 0,
				a, 0, b - a, w);
		render.drawElementOfGUI(10, 7, p == (HORIZONTAL | TRACK_FORW) ? 1 : 0,
				b, 0, tmp - b, w);
		render.drawElementOfGUI(10, 3, p == (HORIZONTAL | FORWARD) ? 1 : 0,
				tmp, 0, DEFAULT_SIZE, w);
	}

	public void paintVertScrollBar(Graphics render, ScrollBar scrollbar, int length, int width)
	{
		int w;
		int p;
		int a;
		int b;
		int tmp;
		int page;
		int range;
		w = Math.min(DEFAULT_SIZE, width);
		if((range = scrollbar.getRange()) <= 0 || (page = scrollbar.getPage()) <= 0 ||
				range <= page)
		{
			/* рисуем полностью недоступную полосу прокрутки */
			if(length < DEFAULT_SIZE << 1)
			{
				b = length - (a = length / 2);
				render.drawElementOfGUI(10, 0, 2,
						0, 0, w, a);
				render.drawElementOfGUI(10, 1, 2,
						0, a, w, b);
				return;
			}
			render.drawElementOfGUI(10, 0, 2,
					0, 0, w, DEFAULT_SIZE);
			render.drawElementOfGUI(10, 9, 2,
					0, DEFAULT_SIZE, w, length - (DEFAULT_SIZE << 1));
			render.drawElementOfGUI(10, 1, 2,
					0, length - DEFAULT_SIZE, w, DEFAULT_SIZE);
			return;
		}
		p = pressed;
		if(length < SLIDER_MIN_LENGTH + (DEFAULT_SIZE << 1))
		{
			/* рисуем доступную полосу прокрутки без ползунка */
			if(length < DEFAULT_SIZE << 1)
			{
				b = length - (a = length / 2);
				render.drawElementOfGUI(10, 0, p == (VERTICAL | BACKWARD) ? 1 : 0,
						0, 0, w, a);
				render.drawElementOfGUI(10, 1, p == (VERTICAL | FORWARD) ? 1 : 0,
						0, a, w, b);
				return;
			}
			render.drawElementOfGUI(10, 0, p == (VERTICAL | BACKWARD) ? 1 : 0,
					0, 0, w, DEFAULT_SIZE);
			render.drawElementOfGUI(10, 9, 0,
					0, DEFAULT_SIZE, w, length - (DEFAULT_SIZE << 1));
			render.drawElementOfGUI(10, 1, p == (VERTICAL | FORWARD) ? 1 : 0,
					0, length - DEFAULT_SIZE, w, DEFAULT_SIZE);
			return;
		}
		/* рисуем доступную полосу прокрутки с ползунком */
		tmp = length - (DEFAULT_SIZE << 1);
		b = (a = ScrollBarPaintHelper.getSliderPosition(scrollbar.getPosition(), page, range, tmp,
				b = ScrollBarPaintHelper.getSliderLength(page, range, tmp, SLIDER_MIN_LENGTH)) +
				DEFAULT_SIZE) + b;
		tmp = length - DEFAULT_SIZE;
		render.drawElementOfGUI(10, 0, p == (VERTICAL | BACKWARD) ? 1 : 0,
				0, 0, w, DEFAULT_SIZE);
		render.drawElementOfGUI(10, 8, p == (VERTICAL | TRACK_BACK) ? 1 : 0,
				0, DEFAULT_SIZE, w, a - DEFAULT_SIZE);
		render.drawElementOfGUI(10, 5, p == (VERTICAL | SLIDER) ? 1 : 0,
				0, a, w, b - a);
		render.drawElementOfGUI(10, 9, p == (VERTICAL | TRACK_FORW) ? 1 : 0,
				0, b, w, tmp - b);
		render.drawElementOfGUI(10, 1, p == (VERTICAL | FORWARD) ? 1 : 0,
				0, tmp, w, DEFAULT_SIZE);
	}

	public void onHorzScrollBarPointerPressed(ScrollBar scrollbar, int length, int width,
			int x, int y, int button)
	{
		int f;
		int page;
		switch(f = getScrollBarFocused(scrollbar, page = scrollbar.getPage(), length, width, x, y))
		{
		case BACKWARD:
			scrollbar.scroll(-step);
			break;
		case TRACK_BACK:
			scrollbar.scroll(-page);
			break;
		case SLIDER:
			prev = x;
			break;
		case TRACK_FORW:
			scrollbar.scroll(page);
			break;
		case FORWARD:
			scrollbar.scroll(step);
			break;
		default:
			f = NONE;
			break;
		}
		scrollbar.repaintOwner();
		focused = (f |= HORIZONTAL);
		pressed = f;
	}

	public void onHorzScrollBarPointerDragged(ScrollBar scrollbar, int length, int width,
			int x, int y)
	{
		int f;
		int p;
		int range;
		if((f = focused) == (HORIZONTAL | SLIDER))
		{
			p = prev;
			range = scrollbar.getRange();
			length -= DEFAULT_SIZE << 1;
			scrollbar.scroll((int) (((double) (x - p)) * ((double) range) / ((double) length)));
			prev = x;
			return;
		}
		if(f == HORIZONTAL || pressed == (pressed = (HORIZONTAL |
				getScrollBarFocused(scrollbar, scrollbar.getPage(), length, width, x, y)) != f ?
				NONE : f))
		{
			return;
		}
		scrollbar.repaintOwner();
	}

	public void onHorzScrollBarPointerReleased(ScrollBar scrollbar, int length, int width,
			int x, int y, int button)
	{
		int p;
		int range;
		if(focused == (HORIZONTAL | SLIDER))
		{
			p = prev;
			range = scrollbar.getRange();
			length -= DEFAULT_SIZE << 1;
			scrollbar.scroll((int) (((double) (x - p)) * ((double) range) / ((double) length)));
		}
		p = pressed;
		focused = NONE;
		pressed = NONE;
		if(p == NONE)
		{
			return;
		}
		scrollbar.repaintOwner();
	}

	public void onVertScrollBarPointerPressed(ScrollBar scrollbar, int length, int width,
			int x, int y, int button)
	{
		int f;
		int page;
		switch(f = getScrollBarFocused(scrollbar, page = scrollbar.getPage(), length, width, y, x))
		{
		case BACKWARD:
			scrollbar.scroll(-step);
			break;
		case TRACK_BACK:
			scrollbar.scroll(-page);
			break;
		case SLIDER:
			prev = y;
			break;
		case TRACK_FORW:
			scrollbar.scroll(page);
			break;
		case FORWARD:
			scrollbar.scroll(step);
			break;
		default:
			f = NONE;
			break;
		}
		scrollbar.repaintOwner();
		focused = (f |= VERTICAL);
		pressed = f;
	}

	public void onVertScrollBarPointerDragged(ScrollBar scrollbar, int length, int width,
			int x, int y)
	{
		int f;
		int p;
		int range;
		if((f = focused) == (VERTICAL | SLIDER))
		{
			p = prev;
			range = scrollbar.getRange();
			length -= DEFAULT_SIZE << 1;
			scrollbar.scroll((int) (((double) (y - p)) * ((double) range) / ((double) length)));
			prev = y;
			return;
		}
		if(f == HORIZONTAL || pressed == (pressed = (VERTICAL |
				getScrollBarFocused(scrollbar, scrollbar.getPage(), length, width, y, x)) != f ?
				NONE : f))
		{
			return;
		}
		scrollbar.repaintOwner();
	}

	public void onVertScrollBarPointerReleased(ScrollBar scrollbar, int length, int width,
			int x, int y, int button)
	{
		int p;
		int range;
		if(focused == (VERTICAL | SLIDER))
		{
			p = prev;
			range = scrollbar.getRange();
			length -= DEFAULT_SIZE << 1;
			scrollbar.scroll((int) (((double) (y - p)) * ((double) range) / ((double) length)));
		}
		p = pressed;
		focused = NONE;
		pressed = NONE;
		if(p == NONE)
		{
			return;
		}
		scrollbar.repaintOwner();
	}

	public int getHorzScrollBarWidth()
	{
		return DEFAULT_SIZE;
	}

	public int getVertScrollBarWidth()
	{
		return DEFAULT_SIZE;
	}

	public void setStep(int step)
	{
		this.step = step < 1 ? 1 : step;
	}

	public final int getStep()
	{
		return step;
	}

	private int getScrollBarFocused(ScrollBar scrollbar, int page, int length, int width,
			int inLen, int inWid)
	{
		int a;
		int b;
		int tmp;
		int range;
		int result;
		if((range = scrollbar.getRange()) <= 0 || page <= 0 ||
				range <= page || inWid < 0 || inWid >= Math.min(DEFAULT_SIZE, width))
		{
			return NONE;
		}
		if(length < SLIDER_MIN_LENGTH + (DEFAULT_SIZE << 1))
		{
			if(length < DEFAULT_SIZE << 1)
			{
				a = length / 2;
				result = inLen >= 0 && inLen < a ? BACKWARD :
						inLen >= a && inLen < length ? FORWARD : NONE;
			} else
			{
				result = inLen >= 0 && inLen < DEFAULT_SIZE ? BACKWARD :
						inLen >= length - DEFAULT_SIZE && inLen < length ? FORWARD : NONE;
			}
		} else
		{
			tmp = length - (DEFAULT_SIZE << 1);
			b = (a = ScrollBarPaintHelper.getSliderPosition(scrollbar.getPosition(), page, range,
					tmp, b = ScrollBarPaintHelper.getSliderLength(page, range,
					tmp, SLIDER_MIN_LENGTH)) + DEFAULT_SIZE) + b;
			tmp = length - DEFAULT_SIZE;
			result = inLen >= 0 && inLen < DEFAULT_SIZE ? BACKWARD :
					inLen >= DEFAULT_SIZE && inLen < a ? TRACK_BACK :
					inLen >= a && inLen < b ? SLIDER :
					inLen >= b && inLen < tmp ? TRACK_FORW :
					inLen >= tmp && inLen < length ? FORWARD : NONE;
		}
		return result;
	}
}
