// add any attributes to the renderer
AttributeRenderer.RemoveInfo removes = attrs.addElement(node);
// get the renderers for this tree...
InternalStringBuilder img = new InternalStringBuilder(32);
// Render the beginning of this node
_divState.clear();
String tagId = node.getTagId();
String script = null;
if (tagId != null) {
script = renderTagId(_req, tagId, _divState);
}
attrs.renderDiv(_divState, node);
if (_trs.runAtClient) {
_divState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, TreeElement.TREE_LEVEL, Integer.toString(level));
}
sb.append(" ");
StringBuilderRenderAppender writer = new StringBuilderRenderAppender(sb);
renderBeforeNode(writer, node);
_divRenderer.doStartTag(writer, _divState);
sb.append("\n");
if (script != null)
sb.append(script);
// In devMode we will verify the structure of the tree. This will not run in
// production mode.
ServletContext servletContext = InternalUtils.getServletContext(_req);
boolean devMode = !AdapterManager.getServletContainerAdapter(servletContext).isInProductionMode();
if (devMode) {
boolean error = false;
InternalStringBuilder errorText = new InternalStringBuilder(64);
if (node.getName() == null) {
errorText.append("name");
error = true;
}
if (node.getParent() == null) {
if (error)
errorText.append(", ");
errorText.append("parent");
}
if (error)
registerTagError(Bundle.getString("Tags_TreeStructureError", errorText.toString()), null);
}
// check for tree override properties, the second
// case here is because the root runs through this an by definitions
// has InheritableState == state
InheritableState is = node.getInheritableState();
if (is != null && is != state) {
is.setParent(state);
state = is;
}
// Create the appropriate number of indents
// These are either the spacer.gif if the parent is the last in the line or the
// vertical line gif if the parent is not the last child.
_imgState.clear();
_imgState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, WIDTH, "16px");
_imgState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, BORDER, "0");
_imgState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, ALT, "", false);
for (int i = 0; i < level; i++) {
int levels = level - i;
TreeElement parent = node;
for (int j = 1; j <= levels; j++)
parent = parent.getParent();
img.setLength(0);
img.append(state.getImageRoot());
img.append('/');
if (parent.isLast()) {
img.append(state.getImageSpacer());
_imgState.style = null;
}
else {
img.append(state.getVerticalLineImage());
_imgState.style = "vertical-align:bottom;";
}
sb.append(" ");
_imgState.src = img.toString();
_imageRenderer.doStartTag(writer, _imgState);
_imageRenderer.doEndTag(writer);
sb.append("\n");
}
// boolean flag that will indicate if there is an open anchor created
boolean closeAnchor = false;
if (!_trs.runAtClient)
closeAnchor = renderExpansionAnchor(sb, _anchorRenderer, node, nodeName, state);
else {
// Render client expansion and initialize the tree JavaScript support
closeAnchor = renderClientExpansionAnchor(sb, _anchorRenderer, node, encodedNodeName, state);
}
// place the image into the anchor....
// The type of the image depends upon the position and the type of the node.
String alt = "";
img.setLength(0);
img.append(state.getImageRoot());
img.append('/');
if (node.isLeaf()) { // leaf node either last or middle
if (node.isLast())
img.append(state.getLastLineJoinImage());
else
img.append(state.getLineJoinImage());
}
else if (node.isExpanded()) { // interior node that is expanded
alt = Bundle.getString("Tags_TreeAltTextCollapse", null);
String rImg = null;
if (node.getParent() == null && node instanceof ITreeRootElement) {
rImg = ((ITreeRootElement) node).getRootNodeExpandedImage();
if (rImg != null) {
img.append(rImg);
}
}
if (rImg == null) {
if (node.isLast())
img.append(state.getLastNodeExpandedImage());
else
img.append(state.getNodeExpandedImage());
}
}
else { // interior not expanded
alt = Bundle.getString("Tags_TreeAltTextExpand", null);
String rImg = null;
if (node.getParent() == null && node instanceof ITreeRootElement) {
rImg = ((ITreeRootElement) node).getRootNodeCollapsedImage();
if (rImg != null) {
img.append(rImg);
}
}
if (rImg == null) {
if (node.isLast())
img.append(state.getLastNodeCollapsedImage());
else
img.append(state.getNodeCollapsedImage());
}
}
// write out the image which occurs next to the icon
if (!closeAnchor)
sb.append(" ");
_imgState.clear();
_imgState.src = img.toString();
_imgState.style = "vertical-align:bottom;";
_imgState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, BORDER, "0");
_imgState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, ALT, alt, false);
_imageRenderer.doStartTag(writer, _imgState);
_imageRenderer.doEndTag(writer);
// close the anchor if one was openned...
if (closeAnchor)
_anchorRenderer.doEndTag(writer);
sb.append("\n");
// Calculate the selection link for this node, if the node is disabled, we can skip
// this because a disabled node may not be selected.
String selectionLink = null;
if (!node.isDisabled()) {
// The action on the node overrides all. Otherwise, check to see if there
// is either an href or clientAction. If neither is set, then we inherit the
// action defined on the trees inheritable state.
String action = node.getAction();
if (action == null) {
selectionLink = node.getHref();
if (selectionLink == null && node.getClientAction() != null)
selectionLink = "";
if (selectionLink == null)
action = state.getSelectionAction();
}
// create the selection link
if (action != null && selectionLink == null) {
HashMap params = null;
boolean remove = false;
params = node.getParams();
if (params == null) {
params = new HashMap();
remove = true;
}
params.put(TreeElement.SELECTED_NODE, nodeName);
if (_trs.tagId != null) {
params.put(TreeElement.TREE_ID, _trs.tagId);
}
// Add the jpf ScopeID param if necessary.
String scope = node.getScope();
if (scope != null) {
params.put(ScopedServletUtils.SCOPE_ID_PARAM, scope);
}
String uri = null;
try {
boolean xml = TagRenderingBase.Factory.isXHTML(_req);
uri = PageFlowUtils.getRewrittenActionURI(_servletContext, _req, _res, action, params, null, xml);
}
catch (URISyntaxException e) {
// report the error...
String s = Bundle.getString("Tags_Tree_Node_URLException",
new Object[]{action, e.getMessage()});
registerTagError(s, e);
}
if (remove) {
params.remove(TreeElement.SELECTED_NODE);
if (_trs.tagId != null) {
params.remove(TreeElement.TREE_ID);
}
if (scope != null) {
params.remove(ScopedServletUtils.SCOPE_ID_PARAM);
}
}
if (uri != null) {
selectionLink = _res.encodeURL(uri);
}
}
}
TagRenderingBase endRender = null;
// if there is a selection link we need to put an anchor out.
if (selectionLink != null) {
_anchorState.clear();
_anchorState.href = selectionLink;
String target = node.getTarget();
if (target == null) {
target = state.getSelectionTarget();
}
_anchorState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, TARGET, target);
String title = node.getTitle();
_anchorState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, TITLE, title);
// set the selection styles
if (node.isSelected()) {
_anchorState.style = _trs.selectedStyle;
_anchorState.styleClass = _trs.selectedStyleClass;
}
else {
_anchorState.style = _trs.unselectedStyle;
_anchorState.styleClass = _trs.unselectedStyleClass;
}
if (_anchorState.style == null && _anchorState.styleClass == null) {
_anchorState.style = "text-decoration: none";
}
// render any attributes applied to the HTML
attrs.renderSelectionLink(_anchorState, node);
// render the runAtClient attributes
if (_trs.runAtClient) {
String action = node.getClientAction();
if (action != null) {
action = HtmlUtils.escapeEscapes(action);
action = ScriptRequestState.getString("netuiAction", new Object[]{action});
}
_anchorState.registerAttribute(AbstractHtmlState.ATTR_JAVASCRIPT, ONCLICK, action);
// Jira 299
//_anchorState.onClick = action;
}
// actually render the anchor.
sb.append(" ");
_anchorRenderer.doStartTag(writer, _anchorState);
endRender = _anchorRenderer;
}
else {
// This node doesn's support selection. This means we consider it disabled. We will
// put a span around it and set the style/class to indicate that it is disabled.
_spanState.clear();
_spanState.styleClass = _trs.disabledStyleClass;
_spanState.style = _trs.disabledStyle;
sb.append(" ");
_spanRenderer.doStartTag(writer, _spanState);
endRender = _spanRenderer;
}
sb.append(" ");
// Render the icon for this node, there will always unless the tree turns off default
// icons by setting the useDefaultIcons attribute to false.
String icon = node.getIcon();
if (icon == null) {
icon = state.getIconRoot() + "/" + state.getItemIcon();
}
else {
icon = state.getIconRoot() + "/" + icon;
}
// write out the icon
String label = node.getLabel();
if (icon != null) {
_imgState.clear();
_imgState.src = icon;
_imgState.style = "vertical-align:text-top";
alt = null;
if (label != null && node.isLabelLegalAsAlt())
alt = label;
else
alt = node.getTitle();
if (alt == null)
alt = Bundle.getString("Tags_TreeAltText", null);
_imgState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, ALT, alt, false);
_imgState.registerAttribute(AbstractHtmlState.ATTR_GENERAL, BORDER, "0");
// set the inheritted attributes
attrs.renderIconImage(_imgState, node);
_imageRenderer.doStartTag(writer, _imgState);
_imageRenderer.doEndTag(writer);
sb.append(" ");
}
// Render the label for this node (if any)
if (label != null) {
if (_trs.escapeContent) {
InternalStringBuilder s = new InternalStringBuilder(label.length() + 16);
StringBuilderRenderAppender sbAppend = new StringBuilderRenderAppender(sb);
HtmlUtils.filter(label, sbAppend);
label = s.toString();
}
sb.append(label);
sb.append(" ");
}
endRender.doEndTag(writer);
// if there is content then we should render that here...
String ctnt = node.getContent();
if (ctnt != null) {
if (_trs.escapeContent) {
InternalStringBuilder s = new InternalStringBuilder(ctnt.length() + 16);
StringBuilderRenderAppender sbAppend = new StringBuilderRenderAppender(sb);
HtmlUtils.filter(ctnt, sbAppend);
ctnt = s.toString();
}
sb.append("\n ");
sb.append(ctnt);
}