/*
* This file is part of Matter Overdrive
* Copyright (c) 2015., Simeon Radivoev, All rights reserved.
*
* Matter Overdrive is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Matter Overdrive is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Matter Overdrive. If not, see <http://www.gnu.org/licenses>.
*/
package matteroverdrive.gui.element;
import matteroverdrive.client.data.Color;
import matteroverdrive.gui.MOGuiBase;
import matteroverdrive.gui.events.IListHandler;
import matteroverdrive.util.MOStringHelper;
import matteroverdrive.util.RenderUtils;
import net.minecraft.util.MathHelper;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import static org.lwjgl.opengl.GL11.*;
public class MOElementListBox extends MOElementBase {
IListHandler listHandler;
public int borderColor = new Color(120, 120, 120, 255).getColor();
public int backgroundColor = new Color(0, 0, 0, 255).getColor();
public int selectedLineColor = new Color(0, 0, 0, 255).getColor();
public int textColor = new Color(150, 150, 150, 255).getColor();
public int selectedTextColor = new Color(255, 255, 255, 255).getColor();
private final int _marginTop = 2;
private final int _marginLeft = 2;
private final int _marginRight = 2;
private final int _marginBottom = 2;
private final List<IMOListBoxElement> _elements = new LinkedList<IMOListBoxElement>();
private int _firstIndexDisplayed;
protected int _selectedIndex;
private int scrollHoriz;
public MOElementListBox(MOGuiBase containerScreen,IListHandler listHandler, int x, int y, int width, int height) {
super(containerScreen, x, y, width, height);
this.listHandler = listHandler;
}
public MOElementListBox(MOGuiBase containerScreen, int x, int y, int width, int height)
{
this(containerScreen,containerScreen,x,y,width,height);
}
@Override
public void updateInfo()
{
}
@Override
public void init()
{
}
@Override
public void addTooltip(List<String> var1, int mouseX, int mouseY)
{
}
public void add(IMOListBoxElement element) {
_elements.add(element);
}
public void add(Collection<? extends IMOListBoxElement> elements) {
_elements.addAll(elements);
}
public void remove(IMOListBoxElement element) {
_elements.remove(element);
}
public void removeAt(int index) {
_elements.remove(index);
}
public void clear()
{
_elements.clear();
}
public int getInternalWidth() {
int width = 0;
for (int i = 0; i < getElementCount(); i++) {
width = Math.max(getElementWidth(i), width);
}
return width;
}
public int getInternalHeight() {
int height = 0;
for (int i = 0; i < getElementCount(); i++) {
height += getElementHeight(i);
}
return height;
}
public int getContentWidth() {
return sizeX - _marginLeft - _marginRight;
}
public int getContentHeight() {
return sizeY - _marginTop - _marginBottom;
}
public int getContentTop() {
return posY + _marginTop;
}
public int getContentLeft() {
return posX + _marginLeft;
}
public final int getContentBottom() {
return getContentTop() + getContentHeight();
}
public final int getContentRight() {
return getContentLeft() + getContentWidth();
}
@Override
public void drawBackground(int mouseX, int mouseY, float gameTicks)
{
int heightDrawn = 0;
int nextElement = _firstIndexDisplayed;
glDisable(GL_LIGHTING);
glPushMatrix();
RenderUtils.beginStencil();
drawStencil(getContentLeft(), getContentTop(), getContentRight(), getContentBottom(), 1);
glTranslated(-scrollHoriz, 0, 0);
int e = getElementCount();
while (nextElement < e && heightDrawn <= getContentHeight())
{
if (shouldBeDisplayed(getElement(nextElement))) {
if (this._selectedIndex == nextElement) {
DrawElement(nextElement,getContentLeft(),getContentTop() + heightDrawn,selectedLineColor,selectedTextColor,true,true);
} else {
DrawElement(nextElement,getContentLeft(),getContentTop() + heightDrawn,selectedLineColor,this.textColor,false,true);
}
heightDrawn += getElementHeight(nextElement);
}
nextElement++;
}
RenderUtils.endStencil();
glPopMatrix();
}
@Override
public void drawForeground(int mouseX, int mouseY)
{
int heightDrawn = 0;
int nextElement = _firstIndexDisplayed;
glDisable(GL_LIGHTING);
glPushMatrix();
RenderUtils.beginStencil();
drawStencil(getContentLeft(), getContentTop(), getContentRight(), getContentBottom(), 1);
glTranslated(-scrollHoriz, 0, 0);
int e = getElementCount();
while (nextElement < e && heightDrawn <= getContentHeight())
{
if (shouldBeDisplayed(getElement(nextElement)))
{
if (this._selectedIndex == nextElement) {
DrawElement(nextElement, getContentLeft(), getContentTop() + heightDrawn, selectedLineColor, selectedTextColor, true, false);
} else {
DrawElement(nextElement,getContentLeft(), getContentTop() + heightDrawn, selectedLineColor, this.textColor, false, false);
}
glDisable(GL_STENCIL_TEST);
if (getContentTop() + heightDrawn <= mouseY && getContentTop() + heightDrawn + getElementHeight(nextElement) >= mouseY &&
mouseX >= getContentLeft() && mouseX <= getContentLeft() + getElementWidth(nextElement)) {
drawElementTooltip(nextElement,mouseX,mouseY);
}
glEnable(GL_STENCIL_TEST);
heightDrawn += getElementHeight(nextElement);
}
nextElement++;
}
RenderUtils.endStencil();
glPopMatrix();
}
@Override
public boolean onMousePressed(int mouseX, int mouseY, int mouseButton)
{
int heightChecked = 0;
for (int i = _firstIndexDisplayed; i < getElementCount(); i++)
{
if (heightChecked > getContentHeight()) {
break;
}
if (shouldBeDisplayed(getElement(i)))
{
int elementHeight = getElementHeight(i);
if (getContentTop() + heightChecked <= mouseY && getContentTop() + heightChecked + elementHeight >= mouseY) {
setSelectedIndex(i);
onElementClicked(i,mouseX - getContentLeft(),mouseY - (getContentTop() + heightChecked));
break;
}
heightChecked += elementHeight;
}
}
return true;
}
@Override
public boolean onMouseWheel(int mouseX, int mouseY, int movement) {
if (MOStringHelper.isControlKeyDown()) {
if (movement > 0) {
scrollLeft();
} else if (movement < 0) {
scrollRight();
}
} else {
if (movement > 0) {
scrollUp();
} else if (movement < 0) {
scrollDown();
}
}
return true;
}
public void scrollDown() {
int heightDisplayed = 0;
int elementsDisplayed = 0;
for (int i = _firstIndexDisplayed; i < getElementCount(); i++) {
if (heightDisplayed + getElementHeight(i) > sizeY) {
break;
}
heightDisplayed += getElementHeight(i);
elementsDisplayed++;
}
if (_firstIndexDisplayed + elementsDisplayed < getElementCount()) {
_firstIndexDisplayed++;
}
onScrollV(_firstIndexDisplayed);
}
public void scrollUp() {
if (_firstIndexDisplayed > 0) {
_firstIndexDisplayed--;
}
onScrollV(_firstIndexDisplayed);
}
public void scrollLeft() {
scrollHoriz = Math.max(scrollHoriz - 15, 0);
onScrollH(scrollHoriz);
}
public void scrollRight() {
scrollHoriz = Math.min(scrollHoriz + 15, getLastScrollPositionH());
onScrollH(scrollHoriz);
}
public int getLastScrollPosition() {
int position = getElementCount() - 1;
int heightUsed = getElementHeight(position);
while (position > 0 && heightUsed < sizeY) {
position--;
heightUsed += getElementHeight(position);
}
return position + 1;
}
public int getLastScrollPositionH() {
return Math.max(getInternalWidth() - getContentWidth(), 0);
}
public int getSelectedIndex() {
return _selectedIndex;
}
public int getIndexOf(Object value) {
for (int i = 0; i < _elements.size(); i++) {
if (getElement(i).getValue().equals(value)) {
return i;
}
}
return -1;
}
public IMOListBoxElement getSelectedElement()
{
if(_selectedIndex < getElementCount())
return getElement(MathHelper.clamp_int(_selectedIndex, 0, _elements.size()));
else
return null;
}
public void setSelectedIndex(int index) {
if (index >= 0 && index < getElementCount() && index != _selectedIndex) {
_selectedIndex = index;
onSelectionChanged(_selectedIndex, getSelectedElement());
}
}
public void scrollToV(int index) {
if (index >= 0 && index < getElementCount()) {
_firstIndexDisplayed = index;
}
}
public void scrollToH(int index) {
if (index >= 0 && index <= getLastScrollPositionH()) {
scrollHoriz = index;
}
}
//region indirect Element Access
public void DrawElement(int i,int x,int y,int selectedLineColor,int selectedTextColor, boolean selected,boolean BG)
{
getElement(i).draw(this, x, y, selectedLineColor, selectedTextColor, selected, BG);
}
public void drawElementTooltip(int index,int mouseX,int mouseY)
{
getElement(index).drawToolTop(this, mouseX, mouseY);
}
public int getElementHeight(int id)
{
return _elements.get(id).getHeight();
}
public int getElementWidth(int id)
{
return _elements.get(id).getWidth();
}
protected boolean shouldBeDisplayed(IMOListBoxElement element)
{
return true;
}
public IMOListBoxElement getElement(int index) {
return _elements.get(index);
}
public int getElementCount() {
return _elements.size();
}
//endregion
//region events
protected void onElementClicked(int index,int mousX,int mouseY) {
}
protected void onScrollV(int newStartIndex) {
}
protected void onScrollH(int newStartIndex) {
}
protected void onSelectionChanged(int newIndex, IMOListBoxElement imoListBoxElement)
{
listHandler.ListSelectionChange(getName(),newIndex);
}
//endregion
}