698 lines
20 KiB
Java
698 lines
20 KiB
Java
package speiger.src.coreengine.rendering.gui.components;
|
|
|
|
import java.util.Collection;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.UUID;
|
|
|
|
import speiger.src.collections.objects.lists.ObjectArrayList;
|
|
import speiger.src.collections.objects.sets.ObjectOpenHashSet;
|
|
import speiger.src.collections.objects.sets.ObjectSet;
|
|
import speiger.src.coreengine.math.MathUtils;
|
|
import speiger.src.coreengine.math.misc.ColorUtils;
|
|
import speiger.src.coreengine.math.misc.Facing;
|
|
import speiger.src.coreengine.math.vector.ints.Vec2i;
|
|
import speiger.src.coreengine.rendering.gui.GuiComponent;
|
|
import speiger.src.coreengine.rendering.gui.base.IButtonComponent;
|
|
import speiger.src.coreengine.rendering.gui.components.tree.ITreeEntry;
|
|
import speiger.src.coreengine.rendering.gui.helper.UIShapes;
|
|
import speiger.src.coreengine.rendering.gui.helper.box.IGuiBox;
|
|
import speiger.src.coreengine.rendering.gui.helper.constrains.Constrains;
|
|
import speiger.src.coreengine.rendering.gui.renderer.UIRenderer;
|
|
import speiger.src.coreengine.rendering.gui.renderer.buffer.RenderBuffer;
|
|
import speiger.src.coreengine.rendering.input.Keyboard;
|
|
|
|
public class TreeComponent<T extends ITreeEntry> extends GuiComponent implements IButtonComponent
|
|
{
|
|
public static final int SELECTION_MODE_DISABLE = 0;
|
|
public static final int SELECTION_MODE_SINGLE = 1;
|
|
public static final int SELECTION_MODE_MULTI = 2;
|
|
public static final int SELECTION_MODE_INTERACT = 3;
|
|
|
|
public static final int UPDATE_MODE_DISABLED = 0;
|
|
public static final int UPDATE_MODE_VISIBLE = 1;
|
|
public static final int UPDATE_MODE_OPEN = 2;
|
|
public static final int UPDATE_MODE_ALL = 3;
|
|
|
|
public static final int FLAG_NO_BACKGROUND = 1 << 20;
|
|
|
|
ScrollBarComponent verticalBar = new ScrollBarComponent(ColorUtils.LIGHT_GRAY);
|
|
ScrollBarComponent horizontalBar = new ScrollBarComponent(ColorUtils.LIGHT_GRAY).setHorizontal(true);
|
|
|
|
int color;
|
|
int selectedColor;
|
|
int hoverColor = ColorUtils.LIGHT_GRAY;
|
|
int hoverIndex = -1;
|
|
int dragIndex = -1;
|
|
int movement;
|
|
Vec2i lastMouse = Vec2i.mutable();
|
|
IButtonComponent customButton;
|
|
protected ObjectSet<T> openNodes = new ObjectOpenHashSet<>();
|
|
protected ObjectSet<T> selectedNodes = new ObjectOpenHashSet<>();
|
|
protected int selectionMode = 1;
|
|
protected int updateMode = 1;
|
|
T node;
|
|
float entryHeight;
|
|
|
|
boolean listChange = true;
|
|
List<T> visibleNodes = new ObjectArrayList<T>();
|
|
RenderBuffer buffer;
|
|
|
|
public TreeComponent(int color, float entryHeight)
|
|
{
|
|
super(0F, 0F, 0F, 0F);
|
|
this.entryHeight = entryHeight;
|
|
this.color = color;
|
|
this.selectedColor = color;
|
|
}
|
|
|
|
public TreeComponent(int color, float entryHeight, T entry)
|
|
{
|
|
super(0F, 0F, 0F, 0F);
|
|
this.entryHeight = entryHeight;
|
|
getNodes(entry, openNodes, false);
|
|
this.color = color;
|
|
this.selectedColor = color;
|
|
node = entry;
|
|
if(entry != null)
|
|
{
|
|
entry.calculateDebth();
|
|
}
|
|
}
|
|
|
|
public TreeComponent(float x, float y, float width, float height, int color, float entryHeight, T entry)
|
|
{
|
|
super(x, y, width, height);
|
|
this.entryHeight = entryHeight;
|
|
getNodes(entry, openNodes, false);
|
|
this.color = color;
|
|
node = entry;
|
|
if(entry != null)
|
|
{
|
|
entry.calculateDebth();
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public void init()
|
|
{
|
|
addCloseListener(buffer = getRenderer().createBuffer());
|
|
addChild(horizontalBar, Constrains.scrollBar(verticalBar::isInUse, true, 5F));
|
|
addChild(verticalBar, Constrains.scrollBar(horizontalBar::isInUse, false, 5F));
|
|
List<T> entries = new ObjectArrayList<T>();
|
|
getNodes(node, entries, false);
|
|
for(int i = 0, m = entries.size();i < m;i++)
|
|
{
|
|
entries.get(i).init(this, getGui());
|
|
}
|
|
updateScrollBar();
|
|
createArrow();
|
|
}
|
|
|
|
public TreeComponent<T> setColor(int color)
|
|
{
|
|
if(this.color != color)
|
|
{
|
|
this.color = color;
|
|
onChanged(true);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public TreeComponent<T> setHoverColor(int color)
|
|
{
|
|
hoverColor = color;
|
|
return this;
|
|
}
|
|
|
|
public TreeComponent<T> setSelectionColor(int color)
|
|
{
|
|
selectedColor = color;
|
|
return this;
|
|
}
|
|
|
|
public TreeComponent<T> setEntryHeight(float entryHeight)
|
|
{
|
|
if(this.entryHeight != entryHeight)
|
|
{
|
|
this.entryHeight = entryHeight;
|
|
onChanged(true);
|
|
}
|
|
return this;
|
|
}
|
|
|
|
public TreeComponent<T> setSelectionMode(int mode)
|
|
{
|
|
if(mode < 0 || mode > 3)
|
|
{
|
|
throw new IllegalStateException("Unknown Mode");
|
|
}
|
|
this.selectionMode = mode;
|
|
selectedNodes.clear();
|
|
return this;
|
|
}
|
|
|
|
public TreeComponent<T> setUpdateMode(int mode)
|
|
{
|
|
if(mode < 0 || mode > 3)
|
|
{
|
|
throw new IllegalStateException("Unknown Mode");
|
|
}
|
|
updateMode = mode;
|
|
return this;
|
|
}
|
|
|
|
public TreeComponent<T> disableBackground(boolean value)
|
|
{
|
|
setFlag(FLAG_NO_BACKGROUND, value);
|
|
return this;
|
|
}
|
|
|
|
@Override
|
|
protected void repaint()
|
|
{
|
|
float scale = getBox().getScale();
|
|
List<T> entries = new ObjectArrayList<T>();
|
|
getNodes(node, entries, false);
|
|
for(int i = 0,m=entries.size();i<m;i++)
|
|
{
|
|
entries.get(i).updateState(this, scale);
|
|
}
|
|
updateScrollBar();
|
|
createArrow();
|
|
}
|
|
|
|
public TreeComponent<T> setTree(T entry)
|
|
{
|
|
if(node == entry)
|
|
{
|
|
return this;
|
|
}
|
|
node = entry;
|
|
if(entry != null)
|
|
{
|
|
entry.calculateDebth();
|
|
if(getGui() != null)
|
|
{
|
|
List<T> entries = new ObjectArrayList<T>();
|
|
getNodes(entry, entries, false);
|
|
for(int i = 0,m=entries.size();i<m;i++)
|
|
{
|
|
entries.get(i).init(this, getGui());
|
|
}
|
|
}
|
|
}
|
|
listChange = true;
|
|
openNodes.clear();
|
|
selectedNodes.clear();
|
|
onChanged(true);
|
|
return this;
|
|
}
|
|
|
|
public T getTree()
|
|
{
|
|
return node;
|
|
}
|
|
|
|
public void onTreeChanged()
|
|
{
|
|
listChange = true;
|
|
List<T> entries = new ObjectArrayList<T>();
|
|
getNodes(node, entries, false);
|
|
for(int i = 0,m=entries.size();i<m;i++)
|
|
{
|
|
T entry = entries.get(i);
|
|
if(!entry.isInit())
|
|
{
|
|
entry.init(this, getGui());
|
|
if(!entry.isLeaf() && isOpen((T)entry.getParent()))
|
|
{
|
|
openNode(entry, true);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public boolean isNodeSelected(T entry)
|
|
{
|
|
return selectedNodes.contains(entry);
|
|
}
|
|
|
|
public void addSelectedNode(T entry)
|
|
{
|
|
switch(selectionMode)
|
|
{
|
|
case SELECTION_MODE_DISABLE: return;
|
|
case SELECTION_MODE_SINGLE:
|
|
selectedNodes.clear();
|
|
}
|
|
selectedNodes.add(entry);
|
|
}
|
|
|
|
public void removeSelectedNode(T entry)
|
|
{
|
|
selectedNodes.remove(entry);
|
|
}
|
|
|
|
public void clearSelectedNodes()
|
|
{
|
|
selectedNodes.clear();
|
|
}
|
|
|
|
public boolean hasSelectedNodes()
|
|
{
|
|
return selectedNodes.size() > 0;
|
|
}
|
|
|
|
public T getSelectedNode()
|
|
{
|
|
return selectedNodes.isEmpty() ? null : selectedNodes.iterator().next();
|
|
}
|
|
|
|
public List<T> getSelectedNodes()
|
|
{
|
|
return new ObjectArrayList<T>(this.selectedNodes);
|
|
}
|
|
|
|
public List<T> getOpenNodes()
|
|
{
|
|
return new ObjectArrayList<T>(this.visibleNodes);
|
|
}
|
|
|
|
public List<T> getAllNodes()
|
|
{
|
|
List<T> list = new ObjectArrayList<T>();
|
|
getNodes(node, list, false);
|
|
return list;
|
|
}
|
|
|
|
public void openAll()
|
|
{
|
|
if(node != null)
|
|
{
|
|
openNode(node, true);
|
|
}
|
|
}
|
|
|
|
public void closeAll()
|
|
{
|
|
if(node != null)
|
|
{
|
|
closeNode(node, true);
|
|
}
|
|
}
|
|
|
|
public void openNode(T entry, boolean childrenIncluded)
|
|
{
|
|
openNode(entry, childrenIncluded, Integer.MAX_VALUE);
|
|
}
|
|
|
|
public void openNode(T entry, boolean childrenIncluded, int maxLayers)
|
|
{
|
|
openNodes.add(entry);
|
|
if(childrenIncluded)
|
|
{
|
|
getNodes(entry, openNodes, false, maxLayers);
|
|
}
|
|
listChange = true;
|
|
updateScrollBar();
|
|
}
|
|
|
|
public void toggleNode(T entry, boolean childrenIncluded)
|
|
{
|
|
if(isOpen(entry))
|
|
{
|
|
closeNode(entry, childrenIncluded);
|
|
return;
|
|
}
|
|
openNode(entry, childrenIncluded);
|
|
}
|
|
|
|
public boolean isOpen(T entry)
|
|
{
|
|
return openNodes.contains(entry);
|
|
}
|
|
|
|
public void closeNode(T entry, boolean childrenIncluded)
|
|
{
|
|
openNodes.remove(entry);
|
|
if(childrenIncluded)
|
|
{
|
|
Set<T> entries = new ObjectOpenHashSet<T>();
|
|
getNodes(entry, entries, false);
|
|
openNodes.removeAll(entries);
|
|
}
|
|
listChange = true;
|
|
updateScrollBar();
|
|
}
|
|
|
|
protected void createArrow()
|
|
{
|
|
float pixelSize = (entryHeight * 0.5F);
|
|
UIShapes.createArrow(buffer, pixelSize, pixelSize, color, Facing.EAST);
|
|
UIShapes.createArrow(buffer, pixelSize, pixelSize, color, Facing.SOUTH);
|
|
}
|
|
|
|
protected void updateScrollBar()
|
|
{
|
|
if(listChange)
|
|
{
|
|
listChange = false;
|
|
visibleNodes.clear();
|
|
getNodes(node, visibleNodes, true);
|
|
customButton = null;
|
|
}
|
|
float width = 0F;
|
|
float pixelSize = getBox().getScale() * entryHeight;
|
|
for(int i = 0,m=visibleNodes.size();i<m;i++)
|
|
{
|
|
ITreeEntry entry = visibleNodes.get(i);
|
|
width = Math.max(width, entry.getWidth() + (pixelSize * entry.getDebth()));
|
|
}
|
|
verticalBar.setScrollMax(MathUtils.ceil(visibleNodes.size() * entryHeight));
|
|
horizontalBar.setScrollMax((int)(width / getBox().getScale()));
|
|
horizontalBar.onChanged(true);
|
|
verticalBar.onChanged(true);
|
|
}
|
|
|
|
@Override
|
|
protected boolean fixedUpdateSelf()
|
|
{
|
|
if(updateMode == UPDATE_MODE_ALL)
|
|
{
|
|
for(int i = 0,m=visibleNodes.size();i<m;i++)
|
|
{
|
|
visibleNodes.get(i).onFixedUpdate();
|
|
}
|
|
updateScrollBar();
|
|
}
|
|
else if(updateMode == UPDATE_MODE_VISIBLE)
|
|
{
|
|
int min = getStartIndex();
|
|
int max = min + getIndexWidth();
|
|
for(int i = min,m=visibleNodes.size();i<m&&i<max;i++)
|
|
{
|
|
visibleNodes.get(i).onFixedUpdate();
|
|
}
|
|
updateScrollBar();
|
|
}
|
|
else if(updateMode == UPDATE_MODE_ALL)
|
|
{
|
|
List<T> entries = new ObjectArrayList<T>();
|
|
getNodes(node, entries, false);
|
|
for(int i = 0,m=entries.size();i<m;i++)
|
|
{
|
|
entries.get(i).onFixedUpdate();
|
|
}
|
|
updateScrollBar();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
protected boolean updateSelf(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
if(selectionMode == SELECTION_MODE_DISABLE || !isTopHovered(mouseX, mouseY) || verticalBar.isComponentColliding(mouseX, mouseY) || horizontalBar.isComponentColliding(mouseX, mouseY))
|
|
{
|
|
hoverIndex = -1;
|
|
return true;
|
|
}
|
|
float scale = getBox().getScale();
|
|
mouseY -= getBox().getMinY() - (verticalBar.getScroll() * scale);
|
|
int index = (int)(mouseY / (entryHeight * scale));
|
|
hoverIndex = index < 0 || index >= visibleNodes.size() ? -1 : index;
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
protected boolean renderSelf(int mouseX, int mouseY, float particalTicks)
|
|
{
|
|
float brightness = getActiveBrightness();
|
|
UIRenderer render = getRenderer();
|
|
int start = getStartIndex();
|
|
int end = MathUtils.clamp(0, visibleNodes.size(), start + getIndexWidth());
|
|
IGuiBox box = getBox();
|
|
float scale = box.getScale();
|
|
float minX = horizontalBar.getScroll() * scale;
|
|
float minY = verticalBar.getScroll() * scale;
|
|
float maxX = box.getWidth() - verticalBar.getRequiredSpace() + (horizontalBar.getScroll() * scale);
|
|
float pixelSize = scale * entryHeight;
|
|
float offsetSize = pixelSize * 0.8F;
|
|
if(isFlagNotSet(FLAG_NO_BACKGROUND))
|
|
{
|
|
render.setBrightness(brightness).drawQuad(box, color);
|
|
}
|
|
render.push();
|
|
render.translate(box.getMinX(-horizontalBar.getScroll()), box.getMinY(-verticalBar.getScroll()));
|
|
enableScissorsBox(box.getMinX(), box.getMinY(), box.getMaxX()-verticalBar.getRequiredSpace(), box.getMaxY()-horizontalBar.getRequiredSpace());
|
|
boolean skip = false;
|
|
if(hoverIndex != -1 && hoverIndex >= start && hoverIndex < end)
|
|
{
|
|
T node = visibleNodes.get(hoverIndex);
|
|
float xOffset = (offsetSize + (node.getDebth() * offsetSize * 0.6F)) * 0.8F;
|
|
if(!node.isLeaf() && mouseX - box.getMinX() >= xOffset - (pixelSize * 0.6F) && mouseX - box.getMinX() <= xOffset)
|
|
{
|
|
skip = true;
|
|
}
|
|
if(!skip)
|
|
{
|
|
int extraX = (int)(minX - getBox().getMinX() - xOffset);
|
|
int extraY = (int)(minY - hoverIndex * pixelSize - getBox().getMinY());
|
|
if(node instanceof IButtonComponent && ((IButtonComponent)node).isComponentColliding(mouseX + extraX, mouseY + extraY))
|
|
{
|
|
skip = true;
|
|
}
|
|
}
|
|
float otherMax = node.getHighlightWidth() >= 0F ? xOffset + node.getHighlightWidth() : maxX;
|
|
if(mouseX - box.getMinX() >= otherMax) skip = true;
|
|
if(!skip && selectionMode != SELECTION_MODE_INTERACT)
|
|
{
|
|
float offset = pixelSize * hoverIndex;
|
|
render.drawQuad(minX, offset, Math.min(otherMax, maxX), offset + pixelSize, 0.01F, hoverColor);
|
|
}
|
|
}
|
|
mouseX -= box.getMinX();
|
|
mouseY -= box.getMinY();
|
|
if(selectedNodes.size() > 0)
|
|
{
|
|
render.setBrightness(0.75F * brightness);
|
|
for(int i = start;i<end;i++)
|
|
{
|
|
ITreeEntry entry = visibleNodes.get(i);
|
|
if(selectedNodes.contains(entry))
|
|
{
|
|
float offset = pixelSize * i;
|
|
render.drawQuad(minX, offset, maxX, offset + pixelSize, 0.011F, selectedColor);
|
|
}
|
|
}
|
|
}
|
|
for(int i = start;i<end;i++)
|
|
{
|
|
ITreeEntry entry = visibleNodes.get(i);
|
|
float offsetY = i * pixelSize;
|
|
float offsetX = (offsetSize + (entry.getDebth() * offsetSize * 0.6F)) * 0.8F;
|
|
render.translate(offsetX, offsetY, 0.02F);
|
|
if(!entry.isLeaf())
|
|
{
|
|
boolean extra = skip && i == hoverIndex;
|
|
render.translate(-(pixelSize / 3F), pixelSize * 0.5F).scale(scale);
|
|
render.setBrightness(brightness * (extra ? 0.5F : 1.25F)).drawBuffers(buffer.selectionIterator(openNodes.contains(entry) ? 1 : 0), 0F, 0F);
|
|
render.unscale(scale).translate((pixelSize / 3F), -(pixelSize * 0.5F));
|
|
}
|
|
render.setBrightness(brightness);
|
|
entry.onRender(this, isEnabled(), (int)(mouseX + minX - offsetX), (int)(mouseY + minY - offsetY), particalTicks);
|
|
render.translate(-offsetX, -offsetY, -0.02F);
|
|
}
|
|
render.pop();
|
|
disableScissors();
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void collectTooltips(int mouseX, int mouseY, float particalTicks, Map<UUID, GuiComponent> collector)
|
|
{
|
|
super.collectTooltips(mouseX, mouseY, particalTicks, collector);
|
|
int start = getStartIndex();
|
|
int end = MathUtils.clamp(0, visibleNodes.size(), start + getIndexWidth());
|
|
mouseX -= getBox().getMinX();
|
|
mouseY -= getBox().getMinY();
|
|
float scale = getBox().getScale();
|
|
float minX = horizontalBar.getScroll() * scale;
|
|
float minY = verticalBar.getScroll() * scale;
|
|
float pixelSize = scale * entryHeight;
|
|
float offsetSize = pixelSize * 0.8F;
|
|
for(int i = start;i<end;i++)
|
|
{
|
|
ITreeEntry entry = visibleNodes.get(i);
|
|
float offsetY = i * pixelSize;
|
|
float offsetX = (offsetSize + (entry.getDebth() * offsetSize * 0.6F)) * 0.8F;
|
|
entry.collectTooltips(this, (int)(mouseX + minX - offsetX), (int)(mouseY + minY - offsetY), particalTicks, collector);
|
|
}
|
|
}
|
|
|
|
@Override
|
|
public boolean onClick(int button, int mouseX, int mouseY)
|
|
{
|
|
if(horizontalBar.isInUse() && horizontalBar.isComponentColliding(mouseX, mouseY))
|
|
{
|
|
return horizontalBar.onClick(button, mouseX, mouseY);
|
|
}
|
|
if(verticalBar.isInUse() && verticalBar.isComponentColliding(mouseX, mouseY))
|
|
{
|
|
return verticalBar.onClick(button, mouseX, mouseY);
|
|
}
|
|
if(hoverIndex != -1)
|
|
{
|
|
ITreeEntry entry = visibleNodes.get(hoverIndex);
|
|
float scale = getBox().getScale();
|
|
float offsetSize = entryHeight * scale * 0.8F;
|
|
float offsetX = (offsetSize + (entry.getDebth() * offsetSize * 0.6F)) * 0.8F;
|
|
if(mouseX - getBox().getMinX() >= offsetX - (entryHeight * scale * 0.6F) && mouseX - getBox().getMinX() <= offsetX)
|
|
{
|
|
toggleNode(visibleNodes.get(hoverIndex), Keyboard.isShiftDown());
|
|
return true;
|
|
}
|
|
if(visibleNodes.get(hoverIndex) instanceof IButtonComponent)
|
|
{
|
|
IButtonComponent comp = (IButtonComponent)visibleNodes.get(hoverIndex);
|
|
int extraX = (int)((horizontalBar.getScroll() * scale - getBox().getMinX()) - offsetX);
|
|
int extraY = (int)(verticalBar.getScroll() * scale - (hoverIndex * scale * entryHeight) - getBox().getMinY());
|
|
if(comp.isComponentColliding(mouseX + extraX, mouseY + extraY) && comp.onClick(button, mouseX + extraX, mouseY + extraY))
|
|
{
|
|
customButton = comp;
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
dragIndex = hoverIndex;
|
|
if(selectionMode == SELECTION_MODE_INTERACT)
|
|
{
|
|
dragIndex = -1;
|
|
}
|
|
lastMouse.set(mouseX, mouseY);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public boolean onDrag(int mouseX, int mouseY)
|
|
{
|
|
if(horizontalBar.onDrag(mouseX, mouseY) || verticalBar.onDrag(mouseX, mouseY))
|
|
{
|
|
return true;
|
|
}
|
|
if(customButton != null)
|
|
{
|
|
float scale = getBox().getScale();
|
|
float offsetSize = entryHeight * scale * 0.8F;
|
|
int extraX = (int)((horizontalBar.getScroll() * scale - getBox().getMinX()) - ((offsetSize + (visibleNodes.get(hoverIndex).getDebth() * offsetSize * 0.6F)) * 0.8F));
|
|
int extraY = (int)(verticalBar.getScroll() * scale - (hoverIndex * scale * entryHeight) - getBox().getMinY());
|
|
return customButton.onDrag(mouseX + extraX, mouseY + extraY);
|
|
}
|
|
horizontalBar.addScroll(lastMouse.getX() - mouseX);
|
|
verticalBar.addScroll(lastMouse.getY() - mouseY);
|
|
movement += Math.abs(lastMouse.getX() - mouseX) + Math.abs(lastMouse.getY() - mouseY);
|
|
lastMouse.set(mouseX, mouseY);
|
|
return true;
|
|
}
|
|
|
|
@Override
|
|
public void onRelease(int button, int mouseX, int mouseY)
|
|
{
|
|
horizontalBar.onRelease(button, mouseX, mouseY);
|
|
verticalBar.onRelease(button, mouseX, mouseY);
|
|
if(customButton != null && (hoverIndex >= 0 && hoverIndex < visibleNodes.size() && customButton == visibleNodes.get(hoverIndex)))
|
|
{
|
|
float scale = getBox().getScale();
|
|
float offsetSize = entryHeight * scale * 0.8F;
|
|
int extraX = (int)((horizontalBar.getScroll() * scale - getBox().getMinX()) - ((offsetSize + (visibleNodes.get(hoverIndex).getDebth() * offsetSize * 0.6F)) * 0.8F));
|
|
int extraY = (int)(verticalBar.getScroll() * scale - (hoverIndex * scale * entryHeight) - getBox().getMinY());
|
|
customButton.onRelease(button, mouseX + extraX, mouseY + extraY);
|
|
customButton = null;
|
|
}
|
|
else if(dragIndex != -1 && dragIndex == hoverIndex && movement < 2)
|
|
{
|
|
if(isNodeSelected(visibleNodes.get(hoverIndex)))
|
|
{
|
|
removeSelectedNode(visibleNodes.get(hoverIndex));
|
|
}
|
|
else
|
|
{
|
|
addSelectedNode(visibleNodes.get(hoverIndex));
|
|
}
|
|
notifyListeners(LISTENER_USER_ACTION);
|
|
dragIndex = -1;
|
|
}
|
|
movement = 0;
|
|
}
|
|
|
|
@Override
|
|
public boolean onScroll(int scroll, int mouseX, int mouseY)
|
|
{
|
|
if((horizontalBar.isComponentColliding(mouseX, mouseY) && horizontalBar.onScroll(scroll, mouseX, mouseY)) || (verticalBar.isComponentColliding(mouseX, mouseY) && verticalBar.onScroll(scroll, mouseX, mouseY)))
|
|
{
|
|
movement = 100;
|
|
return true;
|
|
}
|
|
if(hoverIndex != -1 && visibleNodes.get(hoverIndex) instanceof IButtonComponent)
|
|
{
|
|
IButtonComponent comp = (IButtonComponent)visibleNodes.get(hoverIndex);
|
|
float scale = getBox().getScale();
|
|
float offsetSize = entryHeight * scale * 0.8F;
|
|
int extraX = (int)((horizontalBar.getScroll() * scale - getBox().getMinX()) - ((offsetSize + (visibleNodes.get(hoverIndex).getDebth() * offsetSize * 0.6F)) * 0.8F));
|
|
int extraY = (int)(verticalBar.getScroll() - (hoverIndex * getBox().getScale() * entryHeight) - getBox().getMinY());
|
|
if(comp.isComponentColliding(mouseX + extraX, mouseY + extraY) && comp.onScroll(scroll, mouseX + extraX, mouseY + extraY))
|
|
{
|
|
return true;
|
|
}
|
|
}
|
|
if(verticalBar.isInUse())
|
|
{
|
|
verticalBar.addScroll(-(int)(scroll * 5F * getBox().getScale()));
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public int getStartIndex()
|
|
{
|
|
return MathUtils.clamp(0, visibleNodes.size(), MathUtils.floor(verticalBar.getScroll() / entryHeight));
|
|
}
|
|
|
|
public int getIndexWidth()
|
|
{
|
|
return MathUtils.clamp(0, visibleNodes.size(), MathUtils.ceil((getBox().getBaseHeight() - (horizontalBar.getRequiredSpace() / getBox().getScale())) / entryHeight) + 1);
|
|
}
|
|
|
|
protected void getNodes(T entry, Collection<T> collection, boolean openOnly, int layers)
|
|
{
|
|
if(entry != null && layers >= 0)
|
|
{
|
|
collection.add(entry);
|
|
if(!entry.isLeaf() && (!openOnly || openNodes.contains(entry)))
|
|
{
|
|
for(int i = 0,m=entry.getChildCount();i<m;i++)
|
|
{
|
|
getNodes((T)entry.getChild(i), collection, openOnly, layers-1);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
protected void getNodes(T entry, Collection<T> collection, boolean openOnly)
|
|
{
|
|
if(entry != null)
|
|
{
|
|
collection.add(entry);
|
|
if(!entry.isLeaf() && (!openOnly || openNodes.contains(entry)))
|
|
{
|
|
for(int i = 0,m=entry.getChildCount();i<m;i++)
|
|
{
|
|
getNodes((T)entry.getChild(i), collection, openOnly);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|