xapi.ui.html.api.HtmlSnippet Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of xapi-core-ui-html Show documentation
Show all versions of xapi-core-ui-html Show documentation
The core API for generating html from data models.
The newest version!
package xapi.ui.html.api;
import static xapi.collect.X_Collect.newStringMap;
import java.io.IOException;
import javax.inject.Provider;
import com.google.gwt.reflect.shared.GwtReflect;
import xapi.annotation.common.Property;
import xapi.collect.api.StringTo;
import xapi.dev.source.DomBuffer;
import xapi.log.X_Log;
import xapi.source.write.MappedTemplate;
import xapi.ui.api.StyleService;
import xapi.ui.autoui.api.BeanValueProvider;
import xapi.ui.html.api.Style.AlignHorizontal;
import xapi.ui.html.api.Style.AlignVertical;
import xapi.ui.html.api.Style.BorderStyle;
import xapi.ui.html.api.Style.BoxSizing;
import xapi.ui.html.api.Style.Clear;
import xapi.ui.html.api.Style.Cursor;
import xapi.ui.html.api.Style.Display;
import xapi.ui.html.api.Style.Floats;
import xapi.ui.html.api.Style.FontStyle;
import xapi.ui.html.api.Style.FontWeight;
import xapi.ui.html.api.Style.Overflow;
import xapi.ui.html.api.Style.Position;
import xapi.ui.html.api.Style.Rgb;
import xapi.ui.html.api.Style.Transition;
import xapi.ui.html.api.Style.Unit;
import xapi.ui.html.api.Style.UnitType;
import xapi.util.api.ConvertsValue;
import xapi.util.impl.LazyProvider;
public class HtmlSnippet implements ConvertsValue {
public static void appendTo(final Appendable sheet, final Style style) {
try {
doAppend(sheet, style);
} catch (final IOException e) {
X_Log.error(HtmlSnippet.class, "Error rendering",style,e);
}
}
public static void doAppend(final Appendable sheet, final Style style) throws IOException {
append("left", sheet, style.left());
append("right", sheet, style.right());
append("top", sheet, style.top());
append("bottom", sheet, style.bottom());
append("width", sheet, style.width());
append("height", sheet, style.height());
append("max-height", sheet, style.maxHeight());
append("max-width", sheet, style.maxWidth());
append("min-height", sheet, style.minHeight());
append("min-width", sheet, style.minWidth());
if (style.boxSizing() != BoxSizing.Inherit) {
append("box-sizing", sheet, style.boxSizing().styleName);
}
if (style.display() != Display.Inherit) {
append("display", sheet, style.display().styleName());
}
if (style.position() != Position.Inherit) {
append("position", sheet, style.position().styleName());
}
if (style.fontStyle() != FontStyle.Inherit) {
append("font-style", sheet, style.fontStyle().styleName());
}
if (style.fontWeight() != FontWeight.Inherit) {
append("font-weight", sheet, style.fontWeight().styleName());
}
if (style.textAlign() != AlignHorizontal.Auto) {
append("text-align", sheet, style.textAlign().styleName());
}
if (style.verticalAign() != AlignVertical.Auto) {
append("vertical-align", sheet, style.verticalAign().styleName());
}
if (style.cursor() != Cursor.Inherit) {
append("cursor", sheet, style.cursor().styleName());
}
if (style.floats() != Floats.Auto) {
append("float", sheet, style.floats().styleName());
}
if (style.clear() != Clear.Auto) {
append("clear", sheet, style.clear().styleName());
}
if (style.opacity() != 1) {
append("opacity", sheet,Double.toString(style.opacity()));
}
if (style.fontFamily().length > 0) {
final Class extends FontFamily>[] fonts = style.fontFamily();
final StringBuilder b = new StringBuilder();
for (int i = 0, m = fonts.length; i < m; i ++ ) {
if (i > 0) {
b.append(", ");
}
try {
if (fonts[i].isInterface()) {
final Object value = GwtReflect.invoke(fonts[i], "name", new Class>[0], null);
b.append(value);
} else {
b.append(fonts[i].newInstance().name());
}
} catch (final Throwable e) {
X_Log.warn(HtmlSnippet.class, "Error loading font family for "+fonts[i], e);
}
}
sheet.append("font-family").append(":").append(b).append(";");
}
final Transition[] transitions = style.transition();
if (transitions.length > 0) {
final StringBuilder b = new StringBuilder();
for (int i = 0, m = transitions.length; i < m; i ++) {
if (i > 0) {
b.append(", ");
}
final Transition transition = transitions[i];
b
.append(transition.value())
.append(" ")
.append(transition.time())
.append(transition.unit())
;
}
append("transition", sheet, b.toString());
}
if (style.color().length > 0) {
appendColor("color", sheet, style.color()[0]);
}
if (style.backgroundColor().length > 0) {
appendColor("background-color", sheet, style.backgroundColor()[0]);
}
append("font-size", sheet, style.fontSize());
append("line-height", sheet, style.lineHeight());
append("padding", sheet, style.padding(),
style.paddingTop(), style.paddingRight(), style.paddingBottom(), style.paddingLeft());
append("margin", sheet, style.margin(),
style.marginTop(), style.marginRight(), style.marginBottom(), style.marginLeft());
if (style.overflow() != Overflow.Inherit) {
append("overflow", sheet, style.overflow().styleName());
}
if (style.overflowX() != Overflow.Inherit) {
append("overflow-x", sheet, style.overflowX().styleName());
}
if (style.overflowY() != Overflow.Inherit) {
append("overflow-y", sheet, style.overflowY().styleName());
}
for (final Property prop : style.properties()) {
append(prop.name(), sheet, prop.value());
}
final Unit[] borderRadius = style.borderRadius();
if (borderRadius.length > 0) {
sheet.append("border-radius:");
for (final Unit unit : borderRadius) {
sheet.append(" ").append(toString(unit));
}
sheet.append(";");
}
append("border", "width", sheet, style.borderWidth(), style.borderWidthTop(),
style.borderWidthRight(), style.borderWidthBottom(), style.borderWidthLeft());
if (style.borderStyle().length > 0) {
sheet.append("border-style: ");
for (final BorderStyle borderStyle : style.borderStyle()) {
sheet.append(borderStyle.styleName()).append(' ');
}
sheet.append(";");
}
if (style.borderColor().length > 0) {
sheet.append("border-color: ");
for (final Rgb borderColor : style.borderColor()) {
sheet.append(toColor(borderColor)).append(' ');
}
sheet.append(";");
}
}
private static void append(final String type, final Appendable sheet, final String value) throws IOException {
sheet
.append(type)
.append(":")
.append(value)
.append(";");
}
private static void append(final String type, final Appendable sheet, final Unit unit) throws IOException {
if (unit.type() != UnitType.Auto) {
sheet
.append(type)
.append(":")
.append(toString(unit))
.append(";");
}
}
private static void append(final String type, final Appendable sheet, final Unit[] all,
final Unit top, final Unit right, final Unit bottom, final Unit left) throws IOException {
append(type, "", sheet, all, top, right, bottom, left);
}
private static void append(final String type0, final String type1, final Appendable sheet, final Unit unit) throws IOException {
if (unit.type() != UnitType.Auto) {
sheet
.append(type0)
.append(type1)
.append(":")
.append(toString(unit))
.append(";");
}
}
private static void append(final String type, String typeSuffix, final Appendable sheet, final Unit[] all,
final Unit top, final Unit right, final Unit bottom, final Unit left) throws IOException {
if (all.length > 0) {
sheet.append(type).append(":");
for (final Unit unit : all) {
sheet.append(toString(unit));
}
sheet.append(";");
}
if (typeSuffix.length() > 0 && typeSuffix.charAt(0) != '-') {
typeSuffix="-"+typeSuffix;
}
append(type,"-top"+typeSuffix, sheet, top);
append(type,"-right"+typeSuffix, sheet, right);
append(type,"-bottom"+typeSuffix, sheet, bottom);
append(type,"-left"+typeSuffix, sheet, left);
}
private static void appendColor(final String type, final Appendable sheet, final Rgb rgb) throws IOException {
sheet.append(type).append(":");
if (rgb.opacity() == 0xff) {
sheet
.append("#")
.append(toHexString(rgb.r()))
.append(toHexString(rgb.g()))
.append(toHexString(rgb.b()))
;
} else {
sheet
.append("rgba(")
.append(Integer.toString(rgb.r()))
.append(",")
.append(Integer.toString(rgb.g()))
.append(",")
.append(Integer.toString(rgb.b()))
.append(",")
.append(Integer.toString(rgb.opacity()))
.append(")")
;
}
sheet.append(";");
}
private static String toColor(final Rgb rgb) {
if (rgb.opacity() == 0xff) {
return "#"+toHexString(rgb.r())+toHexString(rgb.g())+toHexString(rgb.b());
} else {
return "rgba("+rgb.r()+","+rgb.g()+","+rgb.b()+","+rgb.opacity()+")";
}
}
private static String toHexString(final int r) {
final String s = Integer.toHexString(r);
return s.length() == 1 ? "0"+s: s;
}
private static String toString(final Unit unit) {
final String important = unit.important() ? " !important" : "";
switch (unit.type()) {
case Auto:
return "auto" + important;
case Pct:
return unit.value() + "%"+ important;
case Em:
return unit.value() + "em" + important;
case Px:
return unit.value() + "px" + important;
default:
throw new UnsupportedOperationException("Type "+unit+" not supported");
}
}
protected static final Runnable NO_OP = new Runnable() {
@Override public void run() {}
};
private final Provider> generator;
public HtmlSnippet(
final Html html,
final BeanValueProvider values,
final StyleService> context
) {
assert html != null : "Do not send null @Html to HtmlSnippet!";
assert values != null : "Do not send null BeanValueProvider to HtmlSnippet!";
generator = new LazyProvider<>(new Provider>() {
@Override
public ConvertsValue get() {
return new ConvertsValue() {
@Override
public DomBuffer convert(final T from) {
final DomBuffer buffer = newBuffer(html, from);
final Iterable keys = values.getChildKeys();
for (final El el : html.body()) {
final DomBuffer child = newChild(buffer, el);
for (final Property prop : el.properties()) {
child.setAttribute(prop.name(), toValue(values, keys, prop.value(), from));
}
for (final Style style : el.style()) {
toStyleSheet(style, context);
}
for (final String clsName : el.className()) {
child.addClassName(toValue(values, keys, clsName, from));
}
for (final String html : el.html()) {
final MappedTemplate m = new MappedTemplate(html, keys);
final StringTo