001/*
002 * (C) Copyright 2014 JBoss RichFaces and others.
003 *
004 * All rights reserved. This program and the accompanying materials
005 * are made available under the terms of the GNU Lesser General Public License
006 * (LGPL) version 2.1 which accompanies this distribution, and is available at
007 * http://www.gnu.org/licenses/lgpl-2.1.html
008 *
009 * This library is distributed in the hope that it will be useful,
010 * but WITHOUT ANY WARRANTY; without even the implied warranty of
011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012 * Lesser General Public License for more details.
013 *
014 * Contributors:
015 *     Anahide Tchertchian
016 */
017
018package org.nuxeo.ecm.platform.ui.web.component.radio;
019
020import java.io.IOException;
021
022import javax.faces.component.UIComponent;
023import javax.faces.component.html.HtmlSelectOneRadio;
024import javax.faces.context.FacesContext;
025import javax.faces.context.ResponseWriter;
026
027import org.richfaces.component.util.InputUtils;
028import org.richfaces.renderkit.RenderKitUtils;
029import org.richfaces.renderkit.RendererBase;
030
031/**
032 * Renderer for a single radio button, given a target original radio component and index for original button attributes
033 * retrieval.
034 *
035 * @since 6.0
036 */
037public class SingleRadioRenderer extends RendererBase {
038
039    public static final String RENDERER_TYPE = SingleRadioRenderer.class.getName();
040
041    private String convertToString(Object obj) {
042        return (obj == null ? "" : obj.toString());
043    }
044
045    @Override
046    protected void doEncodeEnd(ResponseWriter writer, FacesContext context, UIComponent _component) throws IOException {
047        UIRadio component = (UIRadio) _component;
048        java.lang.String clientId = component.getClientId(context);
049        final UIComponent targetComponent = getUtils().findComponentFor(component, component.getFor());
050        final javax.faces.model.SelectItem item = component.getSelectItem(context, targetComponent);
051        boolean checked = false;
052        if (targetComponent instanceof javax.faces.component.UIOutput) {
053            final Object currentValue = ((javax.faces.component.UIOutput) targetComponent).getValue();
054            final Object itemValue = item.getValue();
055            checked = itemValue == null ? currentValue == null : itemValue.equals(currentValue);
056        }
057
058        writer.startElement("input", component);
059        writer.writeAttribute("id", clientId, "id");
060        writer.writeAttribute("name", getUtils().clientId(context, targetComponent), "name");
061        writer.writeAttribute("type", "radio", "type");
062        writer.writeAttribute("value", InputUtils.getConvertedStringValue(context, targetComponent, item.getValue()),
063                "value");
064        if (checked) {
065            writer.writeAttribute("checked", "checked", "checked");
066        }
067        if (isDisabled(targetComponent) || isReadonly(targetComponent)) {
068            writer.writeAttribute("disabled", "disabled", "disabled");
069        }
070
071        String targetOnchange = convertToString(RenderKitUtils.getAttributeAndBehaviorsValue(context, targetComponent,
072                RenderKitUtils.attributes().generic("onchange", "onchange", "change", "valueChange").first()));
073        String onchange = convertToString(RenderKitUtils.getAttributeAndBehaviorsValue(context, component,
074                RenderKitUtils.attributes().generic("onchange", "onchange", "change", "valueChange").first()));
075        if (targetOnchange != null && !targetOnchange.trim().isEmpty()) {
076            onchange = onchange == null ? targetOnchange : targetOnchange + ";" + onchange;
077        }
078        if (onchange != null && onchange.trim().length() > 0) {
079            writer.writeAttribute("onchange", onchange, "onchange");
080        }
081        getUtils().encodeAttributesFromArray(
082                context,
083                component,
084                new String[] { "accept", "accesskey", "align", "alt", "checked", "dir", "disabled", "lang",
085                        "maxlength", "onblur", "onclick", "ondblclick", "onfocus", "onkeydown", "onkeypress",
086                        "onkeyup", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onselect",
087                        "readonly", "size", "src", "style", "tabindex", "title", "usemap", "xml:lang" });
088
089        writer.endElement("input");
090        writer.startElement("label", component);
091        writer.writeAttribute("for", clientId, "for");
092        writer.writeText(convertToString(item.getLabel()), null);
093        writer.endElement("label");
094    }
095
096    @Override
097    protected Class<? extends UIComponent> getComponentClass() {
098        return UIRadio.class;
099    }
100
101    private boolean isDisabled(UIComponent targetComponent) {
102        if (targetComponent instanceof HtmlSelectOneRadio) {
103            return ((HtmlSelectOneRadio) targetComponent).isDisabled();
104        } else {
105            final Object disabled = targetComponent.getAttributes().get("disabled");
106            return Boolean.TRUE.equals(disabled);
107        }
108    }
109
110    private boolean isReadonly(UIComponent targetComponent) {
111        if (targetComponent instanceof HtmlSelectOneRadio) {
112            return ((HtmlSelectOneRadio) targetComponent).isReadonly();
113        } else {
114            final Object readonly = targetComponent.getAttributes().get("readonly");
115            return Boolean.TRUE.equals(readonly);
116        }
117    }
118}