package org.openflexo.swing.layout;
import java.awt.Rectangle;
import java.io.IOException;
import java.util.List;
import java.util.StringTokenizer;
import org.openflexo.swing.layout.MultiSplitLayout.Divider;
import org.openflexo.swing.layout.MultiSplitLayout.Leaf;
import org.openflexo.swing.layout.MultiSplitLayout.Node;
import org.openflexo.swing.layout.MultiSplitLayout.Split;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.JsonWriter;
public class NodeAdapter extends TypeAdapter<Node> {
private static enum Types {
LEAF(Leaf.class), SPLIT(Split.class), DIVIDER(Divider.class);
private Class<? extends Node> type;
private Types(Class<? extends Node> type) {
this.type = type;
}
public Class<? extends Node> getType() {
return type;
}
public static NodeAdapter.Types getTypeForClass(Class<? extends Node> type) {
for (NodeAdapter.Types t : values()) {
if (t.getType().isAssignableFrom(type)) {
return t;
}
}
return null;
}
}
private TypeAdapter<List<Node>> listAdapter;
public NodeAdapter(TypeAdapter<List<Node>> collectionAdapter) {
super();
this.listAdapter = collectionAdapter;
}
private String toString(Rectangle rect) {
return "[" + rect.x + "," + rect.y + "," + rect.width + "," + rect.height + "]";
}
private Rectangle fromString(String string) {
StringTokenizer tokenizer = new StringTokenizer(string, "[],");
Rectangle rect = new Rectangle();
rect.x = Integer.valueOf(tokenizer.nextToken());
rect.y = Integer.valueOf(tokenizer.nextToken());
rect.width = Integer.valueOf(tokenizer.nextToken());
rect.height = Integer.valueOf(tokenizer.nextToken());
return rect;
}
@Override
public void write(JsonWriter out, Node value) throws IOException {
out.beginObject();
out.name("type");
out.value(Types.getTypeForClass(value.getClass()).name());
if (!(value instanceof Divider)) {
out.name("weight");
out.value(value.getWeight());
}
out.name("visible");
out.value(value.isVisible());
out.name("bounds");
out.value(toString(value.getBounds()));
String name = null;
if (value instanceof Split) {
Split split = (Split) value;
name = split.getName();
out.name("rowLayout");
out.value(split.isRowLayout());
out.name("children");
listAdapter.write(out, split.getChildren());
} else if (value instanceof Leaf) {
name = ((Leaf) value).getName();
}
if (name != null) {
out.name("name");
out.value(name);
}
out.endObject();
}
@Override
public Node read(JsonReader in) throws IOException {
if (in.peek() == JsonToken.NULL) {
in.nextNull();
return null;
}
in.beginObject();
String name = in.nextName();
NodeAdapter.Types t = Types.valueOf(in.nextString());
Node node;
try {
node = t.getType().newInstance();
} catch (InstantiationException e) {
e.printStackTrace();
throw new RuntimeException(e);
} catch (IllegalAccessException e) {
e.printStackTrace();
throw new RuntimeException(e);
}
while (in.hasNext()) {
name = in.nextName();
if (name.equals("weight")) {
double weight = in.nextDouble();
node.setWeight(weight);
} else if (name.equals("visible")) {
boolean visible = in.nextBoolean();
node.setVisible(visible);
} else if (name.equals("bounds")) {
Rectangle bounds = fromString(in.nextString());
node.setBounds(bounds);
} else if (name.equals("rowLayout")) {
Split split = (Split) node;
boolean rowLayout = in.nextBoolean();
split.setRowLayout(rowLayout);
} else if (name.equals("children")) {
Split split = (Split) node;
List<Node> children = listAdapter.read(in);
split.setChildren(children);
} else if (name.equals("name")) {
String nameValue = in.nextString();
if (node instanceof Leaf) {
((Leaf) node).setName(nameValue);
} else if (node instanceof Split) {
((Split) node).setName(nameValue);
}
}
}
in.endObject();
return node;
}
}