package net.alcuria.umbracraft.editor.modules; import java.util.Comparator; import java.util.HashSet; import java.util.Set; import net.alcuria.umbracraft.definitions.Definition; import net.alcuria.umbracraft.definitions.ListDefinition; import net.alcuria.umbracraft.editor.widget.WidgetUtils; import net.alcuria.umbracraft.listeners.Listener; import net.alcuria.umbracraft.util.StringUtils; import com.badlogic.gdx.Gdx; import com.badlogic.gdx.graphics.Color; import com.badlogic.gdx.scenes.scene2d.InputEvent; import com.badlogic.gdx.scenes.scene2d.ui.Table; import com.badlogic.gdx.scenes.scene2d.utils.ClickListener; import com.badlogic.gdx.utils.Array; import com.badlogic.gdx.utils.Json; import com.badlogic.gdx.utils.JsonWriter.OutputType; import com.badlogic.gdx.utils.ObjectMap; import com.kotcrab.vis.ui.widget.VisLabel; import com.kotcrab.vis.ui.widget.VisTextButton; /** A module to display a generic list of some definition types. * @author Andrew Keturi * @param <T> */ @SuppressWarnings("rawtypes") public abstract class ListModule<T extends Definition> extends Module<ListDefinition> { private final Array<VisTextButton> buttons = new Array<VisTextButton>(); private Definition currentIndex; private T definition; private final Set<String> expandedTags = new HashSet<String>(); private Table menu; private final Array<Definition> sortedDefinitions = new Array<Definition>(); private final Table view; public ListModule() { super(); load(ListDefinition.class); if (rootDefinition == null) { rootDefinition = new ListDefinition<T>(); } view = new Table(); } /** Adds an item to the list of definitions. */ public abstract void addListItem(); private void clearView() { view.clear(); view.add(new VisLabel("Select an item from the left.")); } /** Creates the ui in the right pane * @param definition the definition to use * @param content the {@link Table} containing the content */ public abstract void create(T definition, Table content); @Override public abstract String getTitle(); private Table menu() { return new Table() { { update(); } private Listener addListener() { return new Listener() { @Override public void invoke() { addListItem(); menu.clear(); menu.add(menu()).expandY().fill().padLeft(5).top(); } }; } private Listener deleteListener() { return new Listener() { @Override public void invoke() { if (currentIndex != null) { rootDefinition.delete(currentIndex); currentIndex = null; menu.clear(); menu.add(menu()).expandY().fill().padLeft(5).top(); clearView(); } } }; } private void update() { clear(); defaults().uniformX().fillX().expandX(); // sort all definitions sortedDefinitions.clear(); for (Object i : rootDefinition.keys()) { final String idx = (String) i; sortedDefinitions.add(rootDefinition.get(idx)); } sortedDefinitions.sort(new Comparator<Definition>() { @Override public int compare(Definition def, Definition otherDef) { if (def.getTag().equals(otherDef.getTag())) { return def.getName().compareTo(otherDef.getName()); } return def.getTag().compareTo(otherDef.getTag()); } }); // display buttons.clear(); String heading = null; for (final Definition d : sortedDefinitions) { if (d.getTag() != null && !d.getTag().equals(heading)) { heading = d.getTag(); if (expandedTags.size() == 0) { expandedTags.add(heading); } add(new Table() { { add(new VisLabel(StringUtils.isNotEmpty(d.getTag()) ? d.getTag() : "Untagged")).expandX(); add(WidgetUtils.button(expandedTags.contains(d.getTag()) ? "-" : "+", new Listener() { @Override public void invoke() { if (expandedTags.contains(d.getTag())) { expandedTags.remove(d.getTag()); } else { expandedTags.add(d.getTag()); } update(); } })).size(15); } }).expandX().width(200).row(); } if (expandedTags.contains(d.getTag())) { final VisTextButton button = new VisTextButton(d.getName()); button.addListener(new ClickListener() { @Override public void clicked(InputEvent event, float x, float y) { view.clear(); create((T) d, view); currentIndex = d; updateHighlighted(button); } }); add(button).row(); buttons.add(button); } } add().expand().fill().row(); add(WidgetUtils.button("Add Item", addListener())).row(); add(WidgetUtils.button("Delete Item", deleteListener())); } }; } @Override public void populate(Table content) { content.add(menu = menu()).expandY().fill().padLeft(5).top(); clearView(); content.add(view).expand().top(); }; @Override public void save() { ObjectMap<String, T> newObjects = new ObjectMap<>(); if (rootDefinition.items() == null) { return; } ObjectMap<String, T> oldObjects = rootDefinition.items(); for (T item : oldObjects.values()) { newObjects.put(item.getName(), item); } rootDefinition.setItems(newObjects); Json json = new Json(); json.setOutputType(OutputType.json); String jsonStr = json.prettyPrint(rootDefinition); Gdx.files.external("umbracraft/" + getTitle().toLowerCase() + ".json").writeString(jsonStr, false); } private void updateHighlighted(VisTextButton highlightedButton) { if (highlightedButton == null) { return; } // highlight for (VisTextButton button : buttons) { button.getLabel().setColor(button == highlightedButton ? Color.YELLOW : Color.WHITE); } } }