package io.github.minecraftgui.models;
import io.github.minecraftgui.controllers.KeyBoard;
import io.github.minecraftgui.controllers.Mouse;
import io.github.minecraftgui.controllers.Render;
import io.github.minecraftgui.controllers.Screen;
import io.github.minecraftgui.models.components.Component;
import io.github.minecraftgui.models.components.Root;
import io.github.minecraftgui.models.components.State;
import io.github.minecraftgui.models.components.Visibility;
import io.github.minecraftgui.models.listeners.OnRemoveListener;
import io.github.minecraftgui.models.repositories.FontRepository;
import io.github.minecraftgui.models.repositories.ImageRepository;
import org.lwjgl.input.Keyboard;
import java.util.ArrayList;
import java.util.HashMap;
/**
* Created by Samuel on 2015-12-12.
*/
public class UserInterface {
private final ImageRepository imageRepository;
private final FontRepository fontRepository;
private final HashMap<String, Component> components;
private final Root root;
private boolean keyboardAssigned = false;
private boolean canPlayerInteractWithGUI = false;
private long updateId = Long.MIN_VALUE;
private Component componentHoveredByTheMouse = null;
private Component componentFocused = null;
private final Screen screen;
private final Render render;
private final Mouse mouse;
private final KeyBoard keyBoard;
private final ArrayList<Component> hoverList1;
private final ArrayList<Component> hoverList2;
private ArrayList<Component> hoverListToAdd;
private ArrayList<Component> hoverListLastUpdate;
public UserInterface(ImageRepository imageRepository, FontRepository fontRepository, Screen screen, Render render, Mouse mouse, KeyBoard keyBoard) {
this.imageRepository = imageRepository;
this.fontRepository = fontRepository;
this.screen = screen;
this.render = render;
this.mouse = mouse;
this.keyBoard = keyBoard;
this.components = new HashMap<>();
this.hoverList1 = new ArrayList<>();
this.hoverList2 = new ArrayList<>();
this.hoverListLastUpdate = hoverList1;
this.hoverListToAdd = hoverList2;
this.root = new Root();
components.put(root.getId(), root);
}
public void setCanPlayerInteractWithGUI(boolean canPlayerInteractWithGUI) {
this.canPlayerInteractWithGUI = canPlayerInteractWithGUI;
}
public Component getComponent(String id){
return components.get(id);
}
public void addComponent(String parentId, Component component){
components.put(component.getId(), component);
components.get(parentId).add(component);
component.addOnRemoveListener(new OnRemoveListener() {
@Override
public void onRemove(Component component) {
components.remove(component.getId());
}
});
}
public void removeComponent(String componentId){
components.get(componentId).remove();
}
public void update(){
updateId++;
root.setHeight(screen.getHeight());
root.setWidth(screen.getWidth());
if (canPlayerInteractWithGUI) {
if (keyboardAssigned)
keyBoard.update(updateId);
mouse.update(updateId);
if (!mouse.isGrabbed()) {
setComponentHoveredByTheMouse();
setComponentFocusMouseAndKeyBoard();
} else
resetComponentHoveredAndFocused();
} else
resetComponentHoveredAndFocused();
for (Component component : root.getChildren())
update(component);
}
private void update(Component component){
if(component.getVisibility() == Visibility.VISIBLE) {
component.update(updateId);
for (Component child : component.getChildren())
update(child);
}
}
//Le component peut �tre autant hover ou active
private void setComponentHoveredByTheMouse(){
ArrayList<Component> temp = hoverListToAdd;
hoverListLastUpdate.clear();
hoverListToAdd = hoverListLastUpdate;
hoverListLastUpdate = temp;
if(componentHoveredByTheMouse != null) {
componentHoveredByTheMouse.setState(State.NORMAL);
componentHoveredByTheMouse = null;
}
for(Component child : root.getChildren())
setComponentHoveredByTheMouse(child);
if(componentHoveredByTheMouse != null) {
Component parent = componentHoveredByTheMouse.getParent();
while(parent != null){
parent.setState(State.HOVER);
hoverListToAdd.add(parent);
parent = parent.getParent();
}
if(mouse.isLeftPressed() || mouse.isRightPressed())
componentHoveredByTheMouse.setState(State.ACTIVE);
else
componentHoveredByTheMouse.setState(State.HOVER);
mouse.setCursor(componentHoveredByTheMouse.getCursor());
}
else
mouse.setCursor(Mouse.Cursor.NORMAL);
for(Component component : hoverListLastUpdate)
if(componentHoveredByTheMouse != component && !hoverListToAdd.contains(component))
component.setState(State.NORMAL);
}
private void resetComponentHoveredAndFocused(){
if(componentHoveredByTheMouse != null) {
componentHoveredByTheMouse.setState(State.NORMAL);
for(Component component : hoverListToAdd)
component.setState(State.NORMAL);
hoverListToAdd.clear();
componentHoveredByTheMouse = null;
mouse.setCursor(Mouse.Cursor.NORMAL);
}
if(componentFocused != null) {
componentFocused.setFocus(false);
componentFocused.setMouse(null);
componentFocused.setKeyBoard(null);
keyboardAssigned = false;
}
}
//Pour setter le component si il est focus et donner ou enlever acces au clavier et a la souris
private void setComponentFocusMouseAndKeyBoard(){
if(keyBoard.getKeyListener(Keyboard.KEY_ESCAPE).isPressed() && keyboardAssigned){
componentFocused.setFocus(false);
componentFocused.setMouse(null);
componentFocused.setKeyBoard(null);
keyboardAssigned = false;
componentFocused = null;
}
else if((mouse.isLeftPressed() || mouse.isMiddlePressed() || mouse.isRightPressed()) && !(mouse.isMiddlePressedLastUpdate() || mouse.isLeftPressedLastUpdate() || mouse.isRightPressedLastUpdate())){
if(componentHoveredByTheMouse != componentFocused){
if(componentFocused != null) {
componentFocused.setFocus(false);
componentFocused.setMouse(null);
componentFocused.setKeyBoard(null);
keyboardAssigned = false;
}
if(componentHoveredByTheMouse != null){
componentFocused = componentHoveredByTheMouse;
componentFocused.setFocus(true);
componentFocused.setMouse(mouse);
componentFocused.setKeyBoard(keyBoard);
keyboardAssigned = true;
}
else
componentFocused = null;
}
else if(componentFocused != null)
componentFocused.setMouse(mouse);
}
}
private void setComponentHoveredByTheMouse(Component component){
if(component.getVisibility() == Visibility.VISIBLE) {
if (component.getShape().isLocationInside(mouse.getX(), mouse.getY()))
componentHoveredByTheMouse = component;
for (Component child : component.getChildren())
setComponentHoveredByTheMouse(child);
}
}
public void draw(){
for(Component component : root.getChildren())
draw(component);
}
private void draw(Component component){
if(component.getVisibility() == Visibility.VISIBLE) {
component.draw(render);
for (Component child : component.getChildren())
draw(child);
}
}
}