package xapi.ui.impl;
import xapi.collect.X_Collect;
import xapi.collect.api.ClassTo;
import xapi.collect.api.IntTo;
import xapi.except.NotImplemented;
import xapi.fu.Lazy;
import xapi.ui.api.UiElement;
import xapi.ui.api.UiFeature;
/**
* @author James X. Nelson (james@wetheinter.net)
* Created on 4/19/16.
*/
public abstract class
AbstractUiElement <Node, Element extends Node, Self extends UiElement<Node, ? extends Node, Self>>
implements UiElement<Node, Element,Self> {
protected Self parent;
protected final IntTo<Self> children;
protected final ClassTo<UiFeature> features;
protected Lazy<Element> element;
public <S extends Self> AbstractUiElement(Class<S> cls) {
children = X_Collect.newList(cls);
features = X_Collect.newClassMap(UiFeature.class);
element = Lazy.deferred1(this::initAndBind);
}
protected final Element initAndBind() {
Element e = initialize();
getUiService().bindNode(e, ui());
return e;
}
public Element initialize() {
throw new NotImplemented("Class " + getClass() + " must implement initialize()");
}
@Override
public Element element() {
return element.out1();
}
@Override
public String toSource() {
throw new NotImplemented(getClass() + " must implement toSource()");
}
public void setElement(Element element) {
assert this.element.isUnresolved() : "Calling setElement after element has already been resolved";
this.element = Lazy.immutable1(element);
final Self was = getUiService().bindNode(element, ui());
assert was == null || was == this : "Binding native node " + element + " to multiple elements;" +
"\nwas: " + was + "," +
"\nis: " + this;
}
@Override
public Self getParent() {
return parent;
}
@Override
public Self setParent(Self parent) {
this.parent = parent;
return ui();
}
public IntTo<Self> getChildren() {
return children;
}
@Override
public <F extends UiFeature, Generic extends F> F getFeature(Class<Generic> cls) {
return (F) features.get(cls);
}
@Override
public <F extends UiFeature, Generic extends F> F addFeature(Class<Generic> cls, F feature) {
final UiFeature result = features.put(cls, feature);
return (F) result;
}
@Override
public boolean equals(Object o) {
if (this == o)
return true;
if (!(o instanceof UiElement))
return false;
final UiElement<?, ?, ?> that = (UiElement<?, ?, ?>) o;
// Ui elements may use referential equality,
// since two elements with the exact same attributes are not actually equal
return element() == that.element();
}
@Override
public int hashCode() {
return element().hashCode();
}
}