
de.larmic.butterfaces.component.renderkit.html_basic.tree.TreeRenderer Maven / Gradle / Ivy
package de.larmic.butterfaces.component.renderkit.html_basic.tree;
import de.larmic.butterfaces.component.html.tree.HtmlTree;
import de.larmic.butterfaces.component.partrenderer.RenderUtils;
import de.larmic.butterfaces.component.partrenderer.StringUtils;
import de.larmic.butterfaces.component.renderkit.html_basic.HtmlBasicRenderer;
import de.larmic.butterfaces.event.TreeNodeSelectionEvent;
import de.larmic.butterfaces.event.TreeNodeSelectionListener;
import de.larmic.butterfaces.model.tree.Node;
import de.larmic.butterfaces.resolver.WebXmlParameters;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.faces.context.ResponseWriter;
import javax.faces.render.FacesRenderer;
import java.io.IOException;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Created by larmic on 24.10.14.
*/
@FacesRenderer(componentFamily = HtmlTree.COMPONENT_FAMILY, rendererType = HtmlTree.RENDERER_TYPE)
public class TreeRenderer extends HtmlBasicRenderer {
private final Map nodes = new HashMap<>();
private Node selectedNode = null;
private boolean nodeIconsFound = false;
private WebXmlParameters webXmlParameters;
@Override
public void encodeBegin(FacesContext context, UIComponent component) throws IOException {
rendererParamsNotNull(context, component);
if (!shouldEncode(component)) {
return;
}
final HtmlTree htmlTree = (HtmlTree) component;
final ResponseWriter writer = context.getResponseWriter();
webXmlParameters = new WebXmlParameters(context.getExternalContext());
writer.startElement(ELEMENT_DIV, htmlTree);
this.writeIdAttribute(context, writer, component);
writer.writeAttribute(ATTRIBUTE_CLASS, "butter-component-tree", null);
final ClientBehaviorContext behaviorContext =
ClientBehaviorContext.createClientBehaviorContext(context,
htmlTree, "click", component.getClientId(context), null);
final Node root = htmlTree.getValue();
nodeIconsFound = false;
this.encodeNode(htmlTree, writer, behaviorContext, root, 0, 0, false, !htmlTree.isHideRootNode());
}
private void encodeNode(final HtmlTree tree,
final ResponseWriter writer,
final ClientBehaviorContext behaviorContext,
final Node node,
final int depth,
final int childNumber,
final boolean collapsed,
final boolean renderNode) throws IOException {
if (renderNode) {
writer.startElement("ul", tree);
writer.startElement("li", tree);
final String nodeNumber = "" + nodes.size();
nodes.put(nodeNumber, node);
if (collapsed) {
writer.writeAttribute(ATTRIBUTE_STYLE, "display: none;", null);
}
writer.startElement(ELEMENT_DIV, tree);
writer.writeAttribute("class", "butter-component-tree-row", null);
// collapse
writer.startElement(ELEMENT_SPAN, tree);
final String collapsingClass = node.isCollapsed() ? webXmlParameters.getExpansionGlyphicon() : webXmlParameters.getCollapsingGlyphicon();
final String nodeClass = node.isLeaf() ? "butter-component-tree-leaf" : "butter-component-tree-node " + collapsingClass;
writer.writeAttribute("class", "butter-component-tree-jquery-marker " + nodeClass, null);
final Map> behaviors = tree.getClientBehaviors();
if (behaviors.containsKey("click")) {
final String click = behaviors.get("click").get(0).getScript(behaviorContext);
if (StringUtils.isNotEmpty(click)) {
final String s = click.replace(",'click',", ",'collapse_" + nodeNumber + "',");
writer.writeAttribute("onclick", s, null);
}
}
writer.endElement(ELEMENT_SPAN);
// icon
writer.startElement(ELEMENT_SPAN, tree);
if (StringUtils.isNotEmpty(node.getImageIcon())) {
writer.writeAttribute(ATTRIBUTE_CLASS, "butter-component-tree-icon", null);
writer.writeAttribute(ATTRIBUTE_STYLE, "background-image:url(" + node.getImageIcon() + ")", null);
nodeIconsFound = true;
} else if (StringUtils.isNotEmpty(node.getGlyphiconIcon())) {
writer.writeAttribute(ATTRIBUTE_CLASS, "butter-component-tree-icon " + node.getGlyphiconIcon(), null);
nodeIconsFound = true;
} else {
writer.writeAttribute(ATTRIBUTE_CLASS, "butter-component-tree-icon", null);
}
writer.endElement(ELEMENT_SPAN);
// title
writer.startElement(ELEMENT_SPAN, tree);
writer.writeAttribute("id", tree.getClientId() + "_" + depth + "_" + childNumber, null);
writer.writeAttribute(ATTRIBUTE_CLASS, "butter-component-tree-title", null);
if (behaviors.containsKey("click")) {
final String click = behaviors.get("click").get(0).getScript(behaviorContext);
// could be empty if ajax tag is disabled
if (StringUtils.isNotEmpty(click)) {
final String s = click.replace(",'click',", ",'click_" + nodeNumber + "',");
final String jQueryPluginCall = RenderUtils.createJQueryPluginCall(tree.getClientId(), "selectTreeNode({nodeNumber:'" + nodeNumber + "'})");
writer.writeAttribute("onclick", s + ";" + jQueryPluginCall, null);
writer.writeAttribute("treenode", nodeNumber, null);
}
}
writer.writeText(node.getTitle(), null);
writer.endElement(ELEMENT_SPAN);
writer.endElement(ELEMENT_DIV);
}
if (!node.isLeaf()) {
final Collection subNodes = node.getSubNodes();
int i = 0;
for (Node subNode : subNodes) {
this.encodeNode(tree, writer, behaviorContext, subNode, depth + 1, i++, isCollapsed(node) || collapsed, true);
}
}
writer.endElement("li");
writer.endElement("ul");
}
@Override
public void encodeEnd(FacesContext context, UIComponent component) throws IOException {
rendererParamsNotNull(context, component);
if (!shouldEncode(component)) {
return;
}
final HtmlTree htmlTree = (HtmlTree) component;
final ResponseWriter writer = context.getResponseWriter();
final String pluginFunctionCall = "butterTree(" + createButterTreeJQueryParameter(htmlTree) + ")";
RenderUtils.renderJQueryPluginCall(htmlTree.getClientId(), pluginFunctionCall, writer, component);
writer.endElement(ELEMENT_DIV);
}
@Override
public void decode(FacesContext context, UIComponent component) {
final HtmlTree htmlTree = (HtmlTree) component;
final TreeNodeSelectionListener nodeSelectionListener = htmlTree.getNodeSelectionListener();
final Map> behaviors = htmlTree.getClientBehaviors();
if (nodeSelectionListener == null) {
return;
}
if (behaviors.isEmpty()) {
return;
}
final ExternalContext external = context.getExternalContext();
final Map params = external.getRequestParameterMap();
final String behaviorEvent = params.get("javax.faces.behavior.event");
if (behaviorEvent != null) {
final String[] split = behaviorEvent.split("_");
final String event = split[0];
final String nodeNumber = split[1];
final Node node = nodes.get(nodeNumber);
if ("click".equals(event)) {
nodeSelectionListener.processValueChange(new TreeNodeSelectionEvent(selectedNode, node));
selectedNode = node;
} else if ("collapse".equals(event)) {
node.setCollapsed(!node.isCollapsed());
}
}
}
private String createButterTreeJQueryParameter(final HtmlTree htmlTree) {
final Map> behaviors = htmlTree.getClientBehaviors();
final boolean treeIconsEnabled = behaviors.containsKey("click");
return "{expansionClass: '" + webXmlParameters.getExpansionGlyphicon() +
"', collapsingClass: '" + webXmlParameters.getCollapsingGlyphicon() +
"', treeSelectionEnabled: '" + treeIconsEnabled +
"', treeIconsEnabled: '" + nodeIconsFound + "'}";
}
private boolean isCollapsed(final Node node) {
return !node.getSubNodes().isEmpty() && node.isCollapsed();
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy