package openmods.gui.component;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import java.util.List;
import net.minecraft.client.Minecraft;
public abstract class BaseComposite extends BaseComponent {
protected final List<BaseComponent> components = Lists.newArrayList();
protected final List<BaseComponent> tickingComponents = Lists.newArrayList();
public BaseComposite(int x, int y) {
super(x, y);
}
protected boolean areChildrenActive() {
return true;
}
public BaseComposite addComponent(BaseComponent component) {
components.add(component);
if (component.isTicking()) tickingComponents.add(component);
return this;
}
private static boolean isComponentEnabled(BaseComponent component) {
return component != null && component.isEnabled();
}
private static boolean isComponentCapturingMouse(BaseComponent component, int mouseX, int mouseY) {
return isComponentEnabled(component) && component.isMouseOver(mouseX, mouseY);
}
protected abstract void renderComponentBackground(Minecraft minecraft, int offsetX, int offsetY, int mouseX, int mouseY);
protected void renderComponentForeground(Minecraft minecraft, int offsetX, int offsetY, int mouseX, int mouseY) {}
@Override
public final void render(Minecraft minecraft, int offsetX, int offsetY, int mouseX, int mouseY) {
renderComponentBackground(minecraft, offsetX, offsetY, mouseX, mouseY);
if (!areChildrenActive()) return;
final int ownX = offsetX + this.x;
final int ownY = offsetY + this.y;
final int relMouseX = mouseX - this.x;
final int relMouseY = mouseY - this.y;
for (BaseComponent component : components)
if (isComponentEnabled(component)) {
component.render(minecraft, ownX, ownY, relMouseX, relMouseY);
}
renderComponentForeground(minecraft, offsetX, offsetY, mouseX, mouseY);
}
protected void renderComponentOverlay(Minecraft minecraft, int offsetX, int offsetY, int mouseX, int mouseY) {}
@Override
public final void renderOverlay(Minecraft minecraft, int offsetX, int offsetY, int mouseX, int mouseY) {
renderComponentOverlay(minecraft, offsetX, offsetY, mouseX, mouseY);
if (!areChildrenActive()) return;
final int ownX = offsetX + this.x;
final int ownY = offsetY + this.y;
final int relMouseX = mouseX - this.x;
final int relMouseY = mouseY - this.y;
for (BaseComponent component : components)
if (isComponentEnabled(component)) {
component.renderOverlay(minecraft, ownX, ownY, relMouseX, relMouseY);
}
}
@Override
public void keyTyped(char keyChar, int keyCode) {
super.keyTyped(keyChar, keyCode);
if (!areChildrenActive()) return;
for (BaseComponent component : components)
if (isComponentEnabled(component)) {
component.keyTyped(keyChar, keyCode);
}
}
// for freezing component list, since element layout may change during listener execution
private List<BaseComponent> selectComponentsCapturingMouse(int mouseX, int mouseY) {
ImmutableList.Builder<BaseComponent> result = ImmutableList.builder();
for (BaseComponent component : components)
if (isComponentCapturingMouse(component, mouseX, mouseY)) result.add(component);
return result.build();
}
@Override
public void mouseDown(int mouseX, int mouseY, int button) {
super.mouseDown(mouseX, mouseY, button);
if (!areChildrenActive()) return;
for (BaseComponent component : selectComponentsCapturingMouse(mouseX, mouseY))
component.mouseDown(mouseX - component.x, mouseY - component.y, button);
}
@Override
public void mouseUp(int mouseX, int mouseY, int button) {
super.mouseUp(mouseX, mouseY, button);
if (!areChildrenActive()) return;
for (BaseComponent component : selectComponentsCapturingMouse(mouseX, mouseY))
component.mouseUp(mouseX - component.x, mouseY - component.y, button);
}
@Override
public void mouseDrag(int mouseX, int mouseY, int button, /* love you */long time) {
super.mouseDrag(mouseX, mouseY, button, time);
if (!areChildrenActive()) return;
for (BaseComponent component : selectComponentsCapturingMouse(mouseX, mouseY))
component.mouseDrag(mouseX - component.x, mouseY - component.y, button, time);
}
@Override
public boolean isTicking() {
return !tickingComponents.isEmpty();
}
@Override
public void tick() {
super.tick();
for (BaseComponent component : tickingComponents)
component.tick();
}
}