/* * Minecraft GUI mod * Copyright (C) 2015 Samuel Marchildon-Lavoie * * This program 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. * * This program 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 this program. If not, see <http://www.gnu.org/licenses/>. */ package io.github.minecraftgui.models.components; import io.github.minecraftgui.controllers.KeyBoard; import io.github.minecraftgui.controllers.Mouse; import io.github.minecraftgui.controllers.Render; import io.github.minecraftgui.models.Updatable; import io.github.minecraftgui.models.attributes.Attribute; import io.github.minecraftgui.models.attributes.AttributeGroupCursor; import io.github.minecraftgui.models.attributes.Position; import io.github.minecraftgui.models.listeners.*; import io.github.minecraftgui.models.shapes.*; import java.util.concurrent.CopyOnWriteArrayList; /** * Created by Samuel on 2015-10-22. */ public abstract class Component implements Updatable, Drawable { private final String id; protected Component parent; protected CopyOnWriteArrayList<Component> children; private final CopyOnWriteArrayList<OnClickListener> onClickListeners; private final CopyOnWriteArrayList<OnDoubleClickListener> onDoubleClickListeners; private final CopyOnWriteArrayList<OnMouseEnterListener> onMouseEnterListeners; private final CopyOnWriteArrayList<OnMouseLeaveListener> onMouseLeaveListeners; private final CopyOnWriteArrayList<OnMouseButtonDownListener> onMouseButtonDownListeners; private final CopyOnWriteArrayList<OnMouseButtonUpListener> onMouseButtonUpListeners; private final CopyOnWriteArrayList<OnKeyPressedListener> onKeyPressedListeners; private final CopyOnWriteArrayList<OnInputListener> onInputListeners; private final CopyOnWriteArrayList<OnBlurListener> onBlurListeners; private final CopyOnWriteArrayList<OnFocusListener> onFocusListeners; private final CopyOnWriteArrayList<OnPasteListener> onPasteListeners; private final CopyOnWriteArrayList<OnCopyListener> onCopyListeners; private final CopyOnWriteArrayList<OnRemoveListener> onRemoveListeners; protected Shape shape; protected KeyBoard keyBoard = null; private Mouse mouse = null; private boolean isFocus = false; private final Position.X x; private final Position.Y y; private AttributeGroupCursor cursor; private Visibility visibility = Visibility.VISIBLE; private State state = State.NORMAL; private boolean mouseOverLastUpdate; public Component(String id, Class<? extends Shape> shape) { this.id = id; this.children = new CopyOnWriteArrayList<>(); this.onClickListeners = new CopyOnWriteArrayList<>(); this.onDoubleClickListeners = new CopyOnWriteArrayList<>(); this.onMouseButtonDownListeners = new CopyOnWriteArrayList<>(); this.onMouseButtonUpListeners = new CopyOnWriteArrayList<>(); this.onMouseEnterListeners = new CopyOnWriteArrayList<>(); this.onMouseLeaveListeners = new CopyOnWriteArrayList<>(); this.onKeyPressedListeners = new CopyOnWriteArrayList<>(); this.onInputListeners = new CopyOnWriteArrayList<>(); this.onBlurListeners = new CopyOnWriteArrayList<>(); this.onFocusListeners = new CopyOnWriteArrayList<>(); this.onPasteListeners = new CopyOnWriteArrayList<>(); this.onCopyListeners = new CopyOnWriteArrayList<>(); this.onRemoveListeners = new CopyOnWriteArrayList<>(); this.x = new Position.X(this); this.y = new Position.Y(this); this.cursor = new AttributeGroupCursor(this); this.shape = getShapeByClass(shape); } public String getId() { return id; } public void addOnClickListener(OnClickListener listener){ onClickListeners.add(listener); } public void addOnRemoveListener(OnRemoveListener listener){ onRemoveListeners.add(listener); } public void addOnDoubleClickListener(OnDoubleClickListener listener){ onDoubleClickListeners.add(listener); } public void addOnMouseButtonDownListener(OnMouseButtonDownListener listener){ onMouseButtonDownListeners.add(listener); } public void addOnMouseButtonUpListener(OnMouseButtonUpListener listener){ onMouseButtonUpListeners.add(listener); } public void addOnMouseEnterListener(OnMouseEnterListener listener){ onMouseEnterListeners.add(listener); } public void addOnMouseLeaveListener(OnMouseLeaveListener listener){ onMouseLeaveListeners.add(listener); } public void addOnKeyPressedListener(OnKeyPressedListener listener){ onKeyPressedListeners.add(listener); } public void addOnInputListener(OnInputListener listener){ onInputListeners.add(listener); } public void addOnBlurListener(OnBlurListener listener){ onBlurListeners.add(listener); } public void addOnFocusListener(OnFocusListener listener){ onFocusListeners.add(listener); } public void addOnCopyListener(OnCopyListener listener){ onCopyListeners.add(listener); } public void addOnPasteListener(OnPasteListener listener){ onPasteListeners.add(listener); } public Component getParent() { return parent; } public Shape getShape() { return shape; } public Attribute<Double> getAttributeWidth(){ return shape.getAttributeWidth(); } public Attribute<Double> getAttributeHeight(){ return shape.getAttributeHeight(); } public boolean isFocus() { return isFocus; } public void setFocus(boolean isFocus) { this.isFocus = isFocus; if(isFocus) onFocus(); else onBlur(); } public void setKeyBoard(KeyBoard keyBoard) { this.keyBoard = keyBoard; } public void setMouse(Mouse mouse) { this.mouse = mouse; } public CopyOnWriteArrayList<Component> getChildren() { return children; } public void add(final Component component){ this.addOnRemoveListener(new OnRemoveListener() { @Override public void onRemove(Component comp) { component.remove(); } }); this.children.add(component); component.parent = this; } public void remove(){ if(this.parent != null) { parent.remove(this); for(OnRemoveListener listener : onRemoveListeners) listener.onRemove(this); } } protected void remove(Component component){ this.children.remove(component); } public void setCursor(State state, Mouse.Cursor cursor) { this.cursor.getAttribute(state).setValue(cursor); } public Mouse.Cursor getCursor(){ return cursor.getValue(); } public Position.X getPositionX() { return x; } public Position.Y getPositionY() { return y; } public double getX(){ return x.getValue(); } public double getY(){ return y.getValue(); } public double getWidth(){ return shape.getWidth(); } public double getHeight(){ return shape.getHeight(); } public State getState() { return state; } public void setState(State state) { this.state = state; } public Visibility getVisibility() { return visibility; } public void setVisibility(Visibility visibility) { this.visibility = visibility; } @Override public void update(long updateId) { cursor.update(updateId); y.update(updateId); x.update(updateId); shape.update(updateId); updateKeyBoard(); updateMouse(); updateMouseOver(); } private void updateMouseOver(){ boolean mouseOver = state == State.HOVER || state == State.ACTIVE; if(mouseOver && !mouseOverLastUpdate) onMouseEnter(); else if(!mouseOver && mouseOverLastUpdate) onMouseLeave(); mouseOverLastUpdate = mouseOver; } private void onMouseLeave(){ for(OnMouseLeaveListener mouseEvent : onMouseLeaveListeners) mouseEvent.onMouseLeave(this); } private void onMouseEnter(){ for(OnMouseEnterListener mouseEvent : onMouseEnterListeners) mouseEvent.onMouseEnter(this); } private void onMouseButtonDown(Mouse mouse, Mouse.Button button){ for(OnMouseButtonDownListener mouseEvent : onMouseButtonDownListeners) mouseEvent.onMouseButtonDown(this, mouse, button); } private void onMouseButtonUp(Mouse mouse, Mouse.Button button){ for(OnMouseButtonUpListener mouseEvent : onMouseButtonUpListeners) mouseEvent.onMouseButtonUp(this, mouse, button); } private void onFocus(){ for(OnFocusListener stateChange : onFocusListeners) stateChange.onFocus(this); } private void onBlur(){ for(OnBlurListener stateChange : onBlurListeners) stateChange.onBlur(this); } private void onClick(){ for(OnClickListener mouseEvent : onClickListeners) mouseEvent.onClick(this, mouse); } private void onDoubleClick(){ for(OnDoubleClickListener mouseEvent : onDoubleClickListeners) mouseEvent.onDoubleClick(this); } private void onInput(char input){ for(OnInputListener keyBoardEvent : onInputListeners) keyBoardEvent.onInput(this, input); } private void onKeyPressed(KeyBoard keyBoard){ for(OnKeyPressedListener keyBoardEvent : onKeyPressedListeners) keyBoardEvent.onKeyPressed(this, keyBoard); } private void onCopy(){ for(OnCopyListener onCopyListener : onCopyListeners) onCopyListener.onCopy(this); } private void onPaste(){ for(OnPasteListener onPasteListener : onPasteListeners) onPasteListener.onPaste(this); } private void updateMouse(){ if(mouse != null) { if (mouse.isClick()) onClick(); if (mouse.isDoubleClick()) onDoubleClick(); if (mouse.isLeftPressed()) onMouseButtonDown(mouse, Mouse.Button.LEFT); else if (mouse.isLeftPressedLastUpdate()) onMouseButtonUp(mouse, Mouse.Button.LEFT); if (mouse.isRightPressed()) onMouseButtonDown(mouse, Mouse.Button.RIGHT); else if (mouse.isRightPressedLastUpdate()) onMouseButtonUp(mouse, Mouse.Button.RIGHT); if (mouse.isMiddlePressed()) onMouseButtonDown(mouse, Mouse.Button.MIDDLE); else if (mouse.isMiddlePressedLastUpdate()) onMouseButtonUp(mouse, Mouse.Button.MIDDLE); } } private void updateKeyBoard(){ if(keyBoard != null){ if(keyBoard.getInput() != 0){ switch(keyBoard.getInput()){ case 3: onCopy(); break; case 22: onPaste(); break; default: onInput(keyBoard.getInput()); break; } } if(keyBoard.isKeyPressed()) onKeyPressed(keyBoard); } } @Override public void draw(Render render) { shape.draw(render); } protected Shape getShapeByClass(Class<? extends Shape> shape){ if(shape == EllipseColor.class) return new EllipseColor(this); else if(shape == PolygonColor.class) return new PolygonColor(this); else if(shape == RectangleColor.class) return new RectangleColor(this); else if(shape == RectangleImage.class) return new RectangleImage(this); return null; } }