package skadistats.clarity.analyzer.replay; import javafx.beans.binding.Bindings; import javafx.beans.binding.ObjectBinding; import javafx.beans.property.ReadOnlyStringWrapper; import javafx.beans.property.StringProperty; import javafx.collections.ObservableListBase; import skadistats.clarity.model.Entity; import skadistats.clarity.model.FieldPath; import java.util.ArrayList; import java.util.Collections; import java.util.Iterator; import java.util.List; public class ObservableEntity extends ObservableListBase<ObservableEntityProperty> { private final Entity entity; private final StringProperty index; private final StringProperty name; private List<FieldPath<? super FieldPath>> indices = new ArrayList<>(); private List<ObservableEntityProperty> properties = new ArrayList<>(); private boolean changeActive = false; public ObservableEntity(Entity entity) { this.entity = entity; index = new ReadOnlyStringWrapper(String.valueOf(entity.getIndex())); name = new ReadOnlyStringWrapper(entity.getDtClass().getDtName()); Iterator<FieldPath> iter = entity.getState().fieldPathIterator(); while (iter.hasNext()) { FieldPath fp = iter.next(); indices.add(fp); properties.add(new ObservableEntityProperty(entity, fp)); } } public ObservableEntity(int index) { this.entity = null; this.index = new ReadOnlyStringWrapper(String.valueOf(index)); this.name = new ReadOnlyStringWrapper(""); } @Override public ObservableEntityProperty get(int index) { return properties.get(index); } @Override public int size() { return indices.size(); } public <F extends FieldPath> int getIndexForFieldPath(F fieldPath) { return Collections.binarySearch(indices, fieldPath); } public ObservableEntityProperty getPropertyForFieldPath(FieldPath fieldPath) { return properties.get(getIndexForFieldPath(fieldPath)); } public <T> ObjectBinding<T> getPropertyBinding(Class<T> propertyClass, String property, T defaultValue) { FieldPath fp = entity.getDtClass().getFieldPathForName(property); if (fp == null) { return Bindings.createObjectBinding(() -> defaultValue); } else { ObjectBinding<T> ob = getPropertyForFieldPath(fp).rawProperty(); return Bindings.createObjectBinding(() -> ob.get(), ob); } } private void ensureChangeOpen() { if (!changeActive) { changeActive = true; beginChange(); } } void commitChange() { if (changeActive) { changeActive = false; endChange(); } for (ObservableEntityProperty property : properties) { if (property.isDirty()) { property.valueProperty().invalidate(); property.rawProperty().invalidate(); property.setDirty(false); } } } void update(FieldPath[] fieldPaths, int num) { for (int i = 0; i < num; i++) { int idx = getIndexForFieldPath(fieldPaths[i]); if (idx < 0) { ensureChangeOpen(); idx = - idx - 1; indices.add(idx, fieldPaths[i]); properties.add(idx, new ObservableEntityProperty(entity, fieldPaths[i])); nextAdd(idx, idx); } else { properties.get(idx).setDirty(true); } } } public String getIndex() { return index.get(); } public StringProperty indexProperty() { return index; } public void setIndex(String index) { this.index.set(index); } public String getName() { return name.get(); } public StringProperty nameProperty() { return name; } public void setName(String name) { this.name.set(name); } public Entity getEntity() { return entity; } @Override public String toString() { return String.format("%s(%s)", getName(), getIndex()); } }