/** * Copyright (c) Lambda Innovation, 2013-2015 * 本作品版权由Lambda Innovation所有。 * http://www.li-dev.cn/ * * This project is open-source, and it is distributed under * the terms of GNU General Public License. You can modify * and distribute freely as long as you follow the license. * 本项目是一个开源项目,且遵循GNU通用公共授权协议。 * 在遵照该协议的情况下,您可以自由传播和修改。 * http://www.gnu.org/licenses/gpl.html */ package cn.liutils.cgui.loader.ui; import java.lang.reflect.Field; import net.minecraft.util.ResourceLocation; import org.lwjgl.opengl.GL11; import cn.liutils.cgui.gui.Widget; import cn.liutils.cgui.gui.component.Component; import cn.liutils.cgui.gui.component.TextBox; import cn.liutils.cgui.gui.component.Tint; import cn.liutils.cgui.gui.event.ChangeContentEvent; import cn.liutils.cgui.gui.event.ChangeContentEvent.ChangeContentHandler; import cn.liutils.cgui.gui.event.ConfirmInputEvent; import cn.liutils.cgui.gui.event.ConfirmInputEvent.ConfirmInputHandler; import cn.liutils.cgui.gui.event.FrameEvent; import cn.liutils.cgui.gui.event.FrameEvent.FrameEventHandler; import cn.liutils.cgui.gui.event.LostFocusEvent; import cn.liutils.cgui.gui.event.LostFocusEvent.LostFocusHandler; import cn.liutils.cgui.gui.event.MouseDownEvent; import cn.liutils.cgui.gui.event.MouseDownEvent.MouseDownHandler; import cn.liutils.util.client.HudUtils; import cn.liutils.util.client.RenderUtils; import cn.liutils.util.helper.Color; import cn.liutils.util.helper.Font; import cn.liutils.util.helper.GameTimer; import cn.liutils.util.helper.TypeHelper; /** * @author WeAthFolD * */ public abstract class ElementEditor extends Widget { ComponentEditor editor; final Field targetField; public ElementEditor(Field f) { targetField = f; } boolean tryEdit(String value) { return TypeHelper.edit(targetField, getEditInstance(), value); } Object getEditInstance() { return getTargetComponent(); } ComponentEditor getEditor() { return editor; } Component getTargetComponent() { return getEditor().target; } void updateTargetWidget() { getEditor().widget.dirty = true; } @Override public void onAdded() { updateValue(); regEventHandler(new FrameEventHandler() { int slowdown = 0; @Override public void handleEvent(Widget w, FrameEvent event) { if(++slowdown >= 30) { slowdown = 0; if(canUpdateValue()) { updateValue(); } } } }); } public abstract void updateValue(); public abstract boolean canUpdateValue(); /** * Default element editor. This is a special one and has hardcoded delegation. */ public static final class Default extends ElementEditor { public Default(Field f) { super(f); } @Override public void updateValue() {} @Override public boolean canUpdateValue() { return false; } } public static final class CheckBox extends ElementEditor { static final ResourceLocation OUTLINE = GuiEdit.tex("check_back"), CHECK = GuiEdit.tex("check"); boolean state; public CheckBox(Field f) { super(f); transform.x = 80; transform.y = -10; transform.setSize(0, 0); } @Override public void onAdded() { super.onAdded(); regEventHandler(new MouseDownHandler() { @Override public void handleEvent(Widget w, MouseDownEvent event) { state = !state; TypeHelper.set(targetField, getEditInstance(), state); } }); regEventHandler(new FrameEventHandler() { boolean firstLoad = true; @Override public void handleEvent(Widget w, FrameEvent event) { if(firstLoad) { firstLoad = false; transform.setSize(10, 10); w.dirty = true; } GL11.glColor4d(1, 1, 1, .8); RenderUtils.loadTexture(OUTLINE); HudUtils.rect(0, 0, 10, 10); if(state) { RenderUtils.loadTexture(CHECK); HudUtils.rect(0, 0, w.transform.width, w.transform.height); } } }); } @Override public void updateValue() { state = (Boolean) TypeHelper.get(targetField, getEditInstance()); } @Override public boolean canUpdateValue() { return true; } } public static class ColorBox extends ElementEditor { public ColorBox(Field f) { super(f); transform.setSize(10, 12); } @Override public Object getEditInstance() { try { return targetField.get(super.getEditInstance()); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public void onAdded() { String[] arr = new String[] { "r", "g", "b", "a" }; double x = 5; for(final String s : arr) { Widget drawer = new Widget(); drawer.regEventHandler(new FrameEventHandler() { @Override public void handleEvent(Widget w, FrameEvent event) { Font.font.draw(s, 0, 2, 8, 0xffffff); } }); drawer.transform.x = x; addWidget(drawer); try { ColorEditor ce = new ColorEditor(s); ce.transform.x = x + 5; ce.transform.width = 20; ce.transform.height = 10; addWidget(ce); } catch (Exception e) { e.printStackTrace(); } x += 30; } } class ColorEditor extends InputBox { public ColorEditor(String sub) throws Exception { super(Color.class.getField(sub)); } @Override public ComponentEditor getEditor() { return ColorBox.this.editor; } @Override Object getEditInstance() { try { return ColorBox.this.getEditInstance(); } catch (Exception e) { e.printStackTrace(); } return null; } @Override public boolean canUpdateValue() { return false; } public boolean setValue() { try { double val = Double.valueOf(((TextBox)getComponent("TextBox")).content) / 255.0; targetField.set(getEditInstance(), val); return true; } catch(Exception e) { e.printStackTrace(); return false; } } @Override public void updateValue() { TextBox.get(this).content = String.valueOf( (int) (((double)TypeHelper.get(targetField, getEditInstance())) * 255) ); } } @Override public void updateValue() {} @Override public boolean canUpdateValue() { return false; } } /** * Input box pref element editor. Default pref for most stuffs. */ public static class InputBox extends ElementEditor { boolean inputDirty; long lastErrorTime = -1; public InputBox(Field f) { super(f); transform.x = 2; transform.width = 120; transform.height = 10; addComponent(new TextBox().setSize(9)); regEventHandler(new FrameEventHandler() { @Override public void handleEvent(Widget w, FrameEvent event) { if(lastErrorTime != -1 && GameTimer.getAbsTime() - lastErrorTime < 1000) { GL11.glColor4d(1, 0, 0, GameTimer.getAbsTime() % 500 < 250 ? 0.6 : 0.3); } else if(inputDirty) { GL11.glColor4d(1, 0.6, 0, 0.3); } else { GL11.glColor4d(1, 1, 1, 0.3); } HudUtils.colorRect(0, 0, w.transform.width, w.transform.height); GL11.glColor4d(1, 1, 1, 1); } }); regEventHandler(new ChangeContentHandler() { @Override public void handleEvent(Widget w, ChangeContentEvent event) { inputDirty = true; } }); regEventHandler(new ConfirmInputHandler() { @Override public void handleEvent(Widget w, ConfirmInputEvent event) { if(inputDirty) { //Try to edit the edit target. if not successful, show error. if(!setValue()) { lastErrorTime = GameTimer.getAbsTime(); } else { updateTargetWidget(); inputDirty = false; } } } }); } public boolean setValue() { return tryEdit(((TextBox)getComponent("TextBox")).content); } @Override public void updateValue() { TextBox.get(this).content = TypeHelper.repr(targetField, getEditInstance()); } @Override public boolean canUpdateValue() { return !inputDirty; } } public static class EnumSelector extends ElementEditor { Object[] enumConstants; TextBox box; Widget list; public EnumSelector(Field f) { super(f); enumConstants = f.getType().getEnumConstants(); transform.setSize(70, 0); transform.setPos(60, -10); } @Override public void onAdded() { transform.setSize(65, 10); box = new TextBox().disallowEdit().setSize(10); addComponent(box); Tint tint = new Tint(); tint.idleColor = new Color(1, 1, 1, 0.3); addComponent(tint); regEventHandler(new MouseDownHandler() { @Override public void handleEvent(Widget w, MouseDownEvent event) { if(list != null) list.dispose(); list = new Widget(); list.transform.setPos(0, 0).setSize(40, 10 * enumConstants.length); for(int i = 0; i < enumConstants.length; ++i) { list.addWidget(new Value(i)); } w.addWidget(list); list.gainFocus(); list.regEventHandler(new LostFocusHandler() { @Override public void handleEvent(Widget w, LostFocusEvent event) { list.dispose(); list = null; } }); } }); super.onAdded(); } @Override public void updateValue() { box.content = TypeHelper.repr(targetField, getEditInstance()); } @Override public boolean canUpdateValue() { return true; } private class Value extends Widget { String name; public Value(int i) { transform.setSize(40, 10); transform.setPos(65, 10 * i); name = enumConstants[i].toString(); addComponent(new TextBox().setSize(10).disallowEdit().setContent(name)); Tint tint = new Tint(); tint.idleColor = new Color(1, 1, 1, 0.3); addComponent(tint); regEventHandler(new MouseDownHandler() { @Override public void handleEvent(Widget w, MouseDownEvent event) { TypeHelper.edit(targetField, getEditInstance(), name); editor.widget.dirty = true; } }); } } } }