package xapi.ui.api;
import xapi.collect.X_Collect;
import xapi.collect.api.IntTo;
import xapi.fu.Immutable;
import xapi.fu.In1;
import xapi.fu.Lazy;
import xapi.fu.Out1;
import xapi.ui.service.UiService;
import xapi.util.X_String;
import xapi.util.api.DebugRethrowable;
/**
* @author James X. Nelson (james@wetheinter.net)
* Created on 4/18/16.
*/
public abstract class UiBuilder <E extends UiElement> implements DebugRethrowable {
private String type;
private String source;
private Out1<UiService> uiService;
private Lazy<IntTo<UiBuilder>> children;
private UiBuilder parent;
protected abstract E instantiate();
private boolean frozen;
protected final Lazy<E> instance;
public UiBuilder() {
this("");
}
public UiBuilder(String type) {
assert type != null : "Specify empty string for null type UiBuilders (lists)";
instance = Lazy.deferBoth(this::initialize, this::instantiate);
uiService = UiService::getUiService;
children = Lazy.deferred1(()->X_Collect.newList(UiBuilder.class));
setType(type);
}
protected void checkNotFrozen() {
assert !frozen : "Do not reuse a UiBuilder (build() has already been called)!" +
" If you want to reuse settings, use the .duplicate() method to clone this instance.";
}
protected E initialize(E inst) {
return inst;
}
public E build() {
E inst = instance.out1();
frozen = true;
return inst;
}
public UiBuilder <E> duplicate() {
try {
UiBuilder copy = getClass().newInstance();
copy.copySettings(this);
return copy;
} catch (Exception e) {
throw rethrow(e);
}
}
protected void copySettings(UiBuilder<E> other) {
this.type = other.type;
this.source = other.source;
}
public UiBuilder<E> setType(String type) {
checkNotFrozen();
this.type = type;
return this;
}
public <Type extends UiElement, Generic extends Type> UiBuilder<Type> addChild(Class<Generic> type) {
final UiBuilder<Type> child = getUiService().newBuilder(type);
child.setParent(this);
return child;
}
public <Type extends UiElement, Generic extends Type> UiBuilder<E> withChild(
Class<Generic> type, In1<UiBuilder<Type>> callback) {
final UiBuilder<Type> child = getUiService().newBuilder(type);
child.setParent(this);
children.out1().add(child);
callback.in(child);
return this;
}
protected void setParent(UiBuilder parent) {
this.parent = parent;
}
protected UiBuilder getParent() {
return parent;
}
public String getType() {
return type;
}
public void setSource(String ... source) {
checkNotFrozen();
this.source = X_String.join("\n", source);
}
public String getOriginalSource() {
return source;
}
public UiService getUiService() {
return uiService.out1();
}
public void setUiService(UiService uiService) {
this.uiService = Immutable.immutable1(uiService);
}
}