/** * 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.gui; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.Set; import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableList; import cpw.mods.fml.relauncher.Side; import cpw.mods.fml.relauncher.SideOnly; /** * A class that has capability to store widgets. Used by LIGui and Widget. * Every widget is associated with a name. You can use that name to lookup a widget. * * This is a internal implementation class. DONT TOUCH IT! * @author WeAthFolD */ @SideOnly(Side.CLIENT) public class WidgetContainer implements Iterable<Widget> { HashBiMap<String, Widget> widgets = HashBiMap.create(); LinkedList<Widget> widgetList = new LinkedList(); //List sorted in non-descending widget zOrder. private static final String UNNAMED_PRE = "Unnamed "; /** * This is light copy. */ public void addAll(WidgetContainer container) { for(Map.Entry<String, Widget> entry : container.getEntries()) { addWidget(entry.getKey(), entry.getValue()); } } /** * Walk the widget list and check their states. This should be called explicitly from tick check events. */ protected void update() { Iterator<Widget> iter = widgetList.iterator(); while(iter.hasNext()) { Widget w = iter.next(); if(w.disposed) { iter.remove(); //TODO: Test efficiency. widgets.inverse().remove(w); } } } /** * @throws NullPointerException if the widget wasn't found. */ public void renameWidget(String name, String newName) { Widget w = widgets.remove(name); if(w == null) throw new NullPointerException(); widgets.put(newName, w); } public Set<Map.Entry<String, Widget>> getEntries() { return widgets.entrySet(); } public boolean addWidget(Widget add) { return addWidget(getNextName(), add); } public boolean addWidget(String name, Widget add) { return addWidget(name, add, false); } public boolean addWidget(Widget add, boolean begin) { return addWidget(getNextName(), add, begin); } /** * Add a widget into the container. * @param name * @param add * @param begin If true the widget will be add at the begin of the draw list. (Draw first), otherwise the last. * @return if the operation is successful. (False for id duplication) */ public boolean addWidget(String name, Widget add, boolean begin) { if(!checkInit(name, add)) return false; if(begin) widgetList.addFirst(add); else widgetList.add(add); checkAdded(name, add); return true; } public boolean addWidgetAfter(String name, Widget add, Widget pivot) { int index = widgetList.indexOf(pivot); if(index == -1) return false; if(!checkInit(name, add)) return false; widgetList.add(index + 1, add); checkAdded(name, add); return true; } public boolean addWidgetBefore(String name, Widget add, Widget pivot) { int index = widgetList.indexOf(pivot); if(index == -1) return false; if(!checkInit(name, add)) return false; widgetList.add(index, add); checkAdded(name, add); return true; } private boolean checkInit(String name, Widget add) { //Check duplicate if(widgets.containsKey(name)) { Widget w = widgets.get(name); if(!w.disposed) { return false; } } widgets.put(name, add); return true; } private void checkAdded(String name, Widget add) { onWidgetAdded(name, add); add.onAdded(); } public void clear() { widgets.clear(); widgetList.clear(); } public Widget getWidget(int i) { return widgetList.get(i); } public int locate(Widget w) { return widgetList.indexOf(w); } /** * Callback when a widget was loaded. Allows lower class to do * some specific data setup. */ protected void onWidgetAdded(String name, Widget w) {} /** * This method supports recursive searching. * For example, you can use "a/b" to get the subWidget named 'b' of a in this * widget container. * @param name Widget name * @return The widget with this name. */ public Widget getWidget(String name) { int ind = name.indexOf('/'); if(ind == -1) { return widgets.get(name); } else if(ind != name.length() - 1){ String cp = name.substring(0, ind); String ep = name.substring(ind + 1); Widget w = widgets.get(cp); return w == null ? null : w.getWidget(ep); } else { return null; } } /** * Check if a widget with given name exists. * @param name Widget name * @return If the widget exists */ public boolean hasWidget(String name) { Widget w = getWidget(name); return w != null && !w.disposed; } /** * Remove a widget from container. */ public void removeWidget(String name) { Widget w = widgets.get(name); if(w != null) { removeWidget(w); } } public void removeWidget(Widget w) { w.dispose(); //w.gui = null; w.parent = null; } public void forceRemoveWidget(Widget w) { if(w.getAbstractParent() != this) return; widgets.remove(w.getName()); widgetList.remove(w); //w.gui = null; w.parent = null; } /** * Get the id of the widget, provided that the widget is in this container. * @return Name of the widget, or null if it's not in this container. */ public String getWidgetName(Widget w) { return widgets.inverse().get(w); } /** * Assign a new name for the widget. */ public void changeWidgetName(Widget w, String newName) { widgets.inverse().put(w, newName); } public List<Widget> getDrawList() { return ImmutableList.copyOf(widgetList); } public Iterator<Widget> iterator() { return getDrawList().iterator(); } /** * Get a next free, auto-generated name for the widget. */ public String getNextName() { String res; int nameCount = 0; do { res = UNNAMED_PRE + (nameCount++); } while(hasWidget(res)); return res; } }