/*
This file is part of jpcsp.
Jpcsp is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
Jpcsp is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Jpcsp. If not, see <http://www.gnu.org/licenses/>.
*/
package jpcsp.format.rco.object;
import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Comparator;
import org.apache.log4j.Logger;
import jpcsp.Emulator;
import jpcsp.format.RCO.RCOEntry;
import jpcsp.format.rco.ObjectField;
import jpcsp.format.rco.RCOContext;
import jpcsp.format.rco.Display;
import jpcsp.format.rco.type.BaseType;
import jpcsp.format.rco.type.EventType;
import jpcsp.format.rco.vsmx.VSMX;
import jpcsp.format.rco.vsmx.interpreter.VSMXBaseObject;
import jpcsp.format.rco.vsmx.interpreter.VSMXInterpreter;
import jpcsp.format.rco.vsmx.interpreter.VSMXNativeObject;
import jpcsp.format.rco.vsmx.interpreter.VSMXString;
import jpcsp.format.rco.vsmx.objects.BaseNativeObject;
import jpcsp.format.rco.vsmx.objects.Controller;
import jpcsp.scheduler.Scheduler;
public abstract class BaseObject extends BaseNativeObject {
protected Logger log = VSMX.log;
protected Display display;
protected Controller controller;
private String name;
private static class FieldComparator implements Comparator<Field> {
@Override
public int compare(Field f1, Field f2) {
ObjectField o1 = f1.getAnnotation(ObjectField.class);
ObjectField o2 = f2.getAnnotation(ObjectField.class);
if (o1 == null || o2 == null) {
return 0;
}
return o1.order() - o2.order();
}
}
private Field[] getFields() {
return getClass().getFields();
}
private Field[] getSortedFields() {
Field fields[] = getFields();
// According the definition of getFields():
// The elements in the array returned are not sorted and are not in any particular order.
// So now, we need to sort the fields according to the "ObjectField" annotation.
Arrays.sort(fields, new FieldComparator());
return fields;
}
public void read(RCOContext context) {
Field[] fields = getSortedFields();
for (Field field : fields) {
if (BaseType.class.isAssignableFrom(field.getType())) {
try {
BaseType baseType = (BaseType) field.get(this);
if (baseType == null) {
baseType = (BaseType) field.getType().newInstance();
field.set(this, baseType);
}
baseType.read(context);
} catch (InstantiationException e) {
// Ignore error
} catch (IllegalAccessException e) {
// Ignore error
}
}
}
}
public int size() {
int size = 0;
Field[] fields = getSortedFields();
for (Field field : fields) {
if (BaseType.class.isAssignableFrom(field.getType())) {
try {
BaseType baseType = (BaseType) field.get(this);
if (baseType == null) {
baseType = (BaseType) field.getType().newInstance();
}
size += baseType.size();
} catch (IllegalAccessException e) {
// Ignore error
} catch (InstantiationException e) {
// Ignore error
}
}
}
return size;
}
public VSMXBaseObject createVSMXObject(VSMXInterpreter interpreter, VSMXBaseObject parent, RCOEntry entry) {
VSMXNativeObject object = new VSMXNativeObject(interpreter, this);
setObject(object);
entry.vsmxBaseObject = object;
if (entry.label != null) {
name = entry.label;
object.setPropertyValue("name", new VSMXString(interpreter, entry.label));
parent.setPropertyValue(entry.label, object);
}
if (entry.parent != null && entry.parent.vsmxBaseObject instanceof VSMXNativeObject) {
setParent(((VSMXNativeObject) entry.parent.vsmxBaseObject).getObject());
}
return object;
}
public void setDisplay(Display display) {
this.display = display;
}
public void onDisplayUpdated() {
display.repaint();
}
public void setController(Controller controller) {
this.controller = controller;
}
protected static Scheduler getScheduler() {
return Emulator.getScheduler();
}
public String getName() {
return name;
}
protected void trigger(EventType event) {
if (event.getEvent() != null) {
controller.getInterpreter().interpretScript(getObject(), event.getEvent());
} else if (event.getObject() != null && event.getObject() instanceof BasePositionObject) {
((BasePositionObject) event.getObject()).setFocus();
}
}
public void init(RCOContext context) {
Field[] fields = getFields();
for (Field field : fields) {
if (BaseType.class.isAssignableFrom(field.getType())) {
try {
BaseType baseType = (BaseType) field.get(this);
if (baseType != null) {
baseType.init(context);
}
} catch (IllegalAccessException e) {
// Ignore error
}
}
}
}
protected void toString(StringBuilder s) {
}
@Override
public String toString() {
StringBuilder s = new StringBuilder();
Field[] fields = getSortedFields();
s.append(String.format("%s[name=%s", getClass().getSimpleName(), name));
boolean firstField = false;
for (Field field : fields) {
if (BaseType.class.isAssignableFrom(field.getType())) {
try {
BaseType baseType = (BaseType) field.get(this);
if (firstField) {
firstField = false;
} else {
s.append(", ");
}
s.append(String.format("%s=(%s)", field.getName(), baseType));
} catch (IllegalAccessException e) {
// Ignore error
}
}
}
toString(s);
s.append("]");
return s.toString();
}
}