package com.indyforge.twod.engine.graphics.rendering.scenegraph.gui;
import java.awt.event.KeyEvent;
import java.util.Iterator;
import com.indyforge.twod.engine.graphics.rendering.scenegraph.Entity;
import com.indyforge.twod.engine.graphics.rendering.scenegraph.EntityFilter;
import com.indyforge.twod.engine.graphics.rendering.scenegraph.EntityRoutines;
import com.indyforge.twod.engine.graphics.rendering.scenegraph.GraphicsEntity;
import com.indyforge.twod.engine.graphics.rendering.scenegraph.Scene;
import com.indyforge.twod.engine.util.iteration.FilteredIterator;
import com.indyforge.twod.engine.util.task.Task;
/**
* Represents a gui entity. Gui entities can be "selected" by using the defaults
* keys.
*
* @author Christopher Probst
*
*/
public class GuiEntity extends GuiListener {
/**
*
*/
private static final long serialVersionUID = 1L;
/*
* The selected and selectable flag.
*/
private boolean selected = false, selectable = true;
/*
* The container of a gui entity.
*/
private final GraphicsEntity container = new GraphicsEntity();
@Override
protected void onSelected(GuiEntity guiEntity) {
super.onSelected(guiEntity);
if (guiEntity == this) {
selected = true;
}
}
@Override
protected void onDeselected(GuiEntity guiEntity) {
super.onDeselected(guiEntity);
if (guiEntity == this) {
selected = false;
}
}
/*
* (non-Javadoc)
*
* @see
* com.indyforge.twod.engine.graphics.rendering.scenegraph.Entity#onUpdate
* (float)
*/
@Override
protected void onUpdate(float tpf) {
super.onUpdate(tpf);
// Find scene
Scene scene = findScene();
// Scene available and selected ?
if (scene != null && selected) {
// Read input values
boolean up = scene.isSinglePressed(KeyEvent.VK_UP), down = scene
.isSinglePressed(KeyEvent.VK_DOWN);
if (up != down) {
// The move dir
int dir = up ? -1 : 1;
// Iterate...
for (int next = cacheIndex() + dir;; next += dir) {
// Check!
if (next < 0) {
next = parent().children().size() - 1;
} else if (next >= parent().children().size()) {
next = 0;
}
// Lookup child
final Entity nextChild = parent().childAt(next);
// If gui entity and selectable... select it !
if (nextChild instanceof GuiEntity
&& ((GuiEntity) nextChild).isSelectable()) {
// Queue the new task
parent().taskQueue()
.tasks()
.offer(new ChangeSelectionTask(this,
(GuiEntity) nextChild));
break;
}
}
}
}
}
private static final class ChangeSelectionTask implements Task {
/**
*
*/
private static final long serialVersionUID = 1L;
/*
* The gui entities.
*/
private final GuiEntity deselect, select;
public ChangeSelectionTask(GuiEntity deselect, GuiEntity select) {
if (deselect == null) {
throw new NullPointerException("deselect");
} else if (select == null) {
throw new NullPointerException("select");
}
this.deselect = deselect;
this.select = select;
}
/*
* (non-Javadoc)
*
* @see com.indyforge.twod.engine.util.task.Task#update(float)
*/
@Override
public boolean update(float tpf) {
deselect.deselect();
select.select();
return true;
}
}
public GuiEntity() {
attach(container);
}
public GuiEntity leave(boolean selectParent) {
if (isSelected()) {
// Delete selection
deselect();
}
// Get gui parent
GuiEntity guiParent = guiParent();
// Hide container
guiParent.guiContainerVisible(false);
// Show all siblings and this entity
guiParent.guiSiblingsVisible(true);
// Should the parent be selected ?
if (selectParent) {
guiParent.select();
}
return this;
}
/**
* Enters the container.
*
* @return this for chaining.
*/
public GuiEntity enter(final int selectionIndex) {
if (isSelected()) {
// Delete selection
deselect();
}
// Hide all siblings and this entity
guiSiblingsVisible(false);
// Make container visible
guiContainerVisible(true);
// Check range
if (selectionIndex >= 0 && selectionIndex < container.children().size()) {
findScene().taskQueue().tasks().offer(new Task() {
/**
*
*/
private static final long serialVersionUID = 1L;
/*
* (non-Javadoc)
*
* @see com.indyforge.twod.engine.util.task.Task#update(float)
*/
@Override
public boolean update(float tpf) {
((GuiEntity) container().childAt(selectionIndex)).select();
return true;
}
});
}
return this;
}
/**
* @param visible
* If true this gui entity (+ components) will be visible,
* otherwise false.
* @return this for chaining.
*/
public GuiEntity guiVisible(boolean visible) {
Iterator<Entity> ptr = new FilteredIterator<Entity>(new EntityFilter() {
/**
*
*/
private static final long serialVersionUID = 1L;
@Override
public boolean accept(Entity element) {
Iterator<Entity> ptr = element.parentIterator(true);
while (ptr.hasNext()) {
if (ptr.next() == container) {
return false;
}
}
return true;
}
}, childIterator(true, true));
EntityRoutines.visible(ptr, visible);
return this;
}
public GuiEntity guiSiblingsVisible(boolean visible) {
Iterator<Entity> itr = siblingIterator(false);
while (itr.hasNext()) {
Entity e = itr.next();
if (e instanceof GuiEntity) {
((GuiEntity) e).guiVisible(visible);
}
}
return this;
}
public GuiEntity guiContainerVisible(boolean visible) {
Iterator<Entity> itr = container.childIterator(false, false);
while (itr.hasNext()) {
Entity e = itr.next();
if (e instanceof GuiEntity) {
((GuiEntity) e).guiVisible(visible);
}
}
return this;
}
/**
* @return the gui parent.
*/
public GuiEntity guiParent() {
return (GuiEntity) parent().parent();
}
/**
* @return the container.
*/
public GraphicsEntity container() {
return container;
}
/**
* Selects this entity.
*
* @return this for chaining.
*/
public GuiEntity select() {
fireEvent(GuiEvent.Selected);
return this;
}
/**
* Deselects this entity.
*
* @return this for chaining.
*/
public GuiEntity deselect() {
fireEvent(GuiEvent.Deselected);
return this;
}
/**
* @return the selectable-flag.
*/
public boolean isSelectable() {
return selectable;
}
/**
* Sets the selectable-flag.
*
* @param selectable
* If true this gui entity can be selected.
* @return this for chaining.
*/
public GuiEntity selectable(boolean selectable) {
this.selectable = selectable;
return this;
}
/**
* @return true if this gui entity is selected, otherwise false.
*/
public boolean isSelected() {
return selected;
}
}