package net.alcuria.umbracraft.editor.modules;
import net.alcuria.umbracraft.definitions.ListDefinition;
import net.alcuria.umbracraft.definitions.area.AreaDefinition;
import net.alcuria.umbracraft.definitions.area.AreaNodeDefinition;
import net.alcuria.umbracraft.definitions.map.MapDefinition;
import net.alcuria.umbracraft.editor.Drawables;
import net.alcuria.umbracraft.editor.Editor;
import net.alcuria.umbracraft.editor.widget.AreaNodeWidget;
import net.alcuria.umbracraft.editor.widget.AreaNodeWidget.NodeClickHandler;
import net.alcuria.umbracraft.editor.widget.TeleportSelectorWidget;
import net.alcuria.umbracraft.editor.widget.WidgetUtils;
import net.alcuria.umbracraft.listeners.Listener;
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.files.FileHandle;
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.ObjectMap;
import com.kotcrab.vis.ui.widget.VisLabel;
import com.kotcrab.vis.ui.widget.VisTextButton;
/** The AreaListModule handles displaying UI for all the {@link AreaDefinition}
* classes within the editor. The layout consists of a tree display of all the
* {@link AreaNodeDefinition} classes in the form of an {@link AreaNodeWidget}
* and a popup that appears over the widget when nodes are clicked to edit node
* properties.
* @author Andrew Keturi */
public class AreaListModule extends ListModule<AreaDefinition> implements NodeClickHandler {
private AreaDefinition areaDefinition; // keep around a reference to the top-level area definition to make rebuilding trees possible
private Table popupTable, widgetTable; // containers for the widget and popup
/** adds a child node to the current definition and rebuilds the
* {@link AreaNodeWidget}
* @param definition the definition to which the child is added */
private void addChild(final AreaNodeDefinition definition) {
if (definition.children == null) {
definition.children = new Array<AreaNodeDefinition>();
}
AreaNodeDefinition child = new AreaNodeDefinition();
child.name = definition.getName() + " Child";
definition.children.add(child);
refresh();
}
@Override
public void addListItem() {
final AreaDefinition area = new AreaDefinition();
area.name = "Area " + (rootDefinition.size() + 1);
rootDefinition.add(area);
}
@Override
public void create(final AreaDefinition definition, Table content) {
if (definition.root == null) {
definition.root = new AreaNodeDefinition();
definition.root.name = "Root";
definition.root.children = new Array<AreaNodeDefinition>();
}
content.add(new Table() {
{
populate(this, AreaDefinition.class, definition, new PopulateConfig());
}
}).row();
areaDefinition = definition;
AreaNodeWidget area = new AreaNodeWidget(definition.root, this);
widgetTable = new Table();
widgetTable.add(area).expand().fill();
content.stack(widgetTable, popupTable = new Table()).expand().fill().row();
content.add(new Table() {
{
add(new Table() {
{
add(WidgetUtils.tooltip("A list of entities present on this area."));
add(new VisLabel("Area Entities:"));
}
}).row();
WidgetUtils.divider(this, "blue");
WidgetUtils.modifiableList(this, definition.entities, new Array<String>(Editor.db().entities().keys()));
}
});
}
private Listener deleteListener(final AreaNodeDefinition definition) {
return new Listener() {
@Override
public void invoke() {
areaDefinition.deleteNode(areaDefinition.root, definition);
refresh();
}
};
}
@Override
public String getTitle() {
return "Areas";
}
@Override
public void onClick(final AreaNodeDefinition definition) {
popupTable.clear();
popupTable.add(new Table() {
{
setBackground(Drawables.get("black"));
// title
WidgetUtils.popupTitle(this, "Editing " + definition.getName(), popupCloseListener());
// content
add(new Table() {
{
PopulateConfig config = new PopulateConfig();
config.cols = 1;
config.suggestions = new ObjectMap<String, Array<String>>();
config.suggestions.put("mapDefinition", new Array<String>() {
{
final FileHandle handle = Gdx.files.external("umbracraft/map.json");
if (handle.exists()) {
ObjectMap<String, MapDefinition> maps = new Json().fromJson(ListDefinition.class, handle).items();
for (MapDefinition map : maps.values()) {
add(map.name);
}
}
}
});
populate(this, AreaNodeDefinition.class, definition, config);
row();
add(new TeleportSelectorWidget(definition).getActor());
}
}).expand().fill().row();
add(new Table() {
{
defaults().pad(10);
// "add child" button
add(new VisTextButton("Add Child") {
{
addListener(new ClickListener() {
@Override
public void clicked(InputEvent event, float x, float y) {
addChild(definition);
}
});
}
});
// delete
add(WidgetUtils.button("Delete", deleteListener(definition)));
}
});
}
}).expand().fill().size(500, 500);
};
private Listener popupCloseListener() {
return new Listener() {
@Override
public void invoke() {
popupTable.clear();
widgetTable.clear();
widgetTable.add(new AreaNodeWidget(areaDefinition.root, AreaListModule.this)).expand().fill();
}
};
}
private void refresh() {
widgetTable.clear();
if (areaDefinition.root == null) {
areaDefinition.root = new AreaNodeDefinition();
}
widgetTable.add(new AreaNodeWidget(areaDefinition.root, this)).expand().fill();
popupTable.clear();
}
}