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 = null;
072        if (targetComponent != null) {
073            targetOnchange = convertToString(RenderKitUtils.getAttributeAndBehaviorsValue(context, targetComponent,
074                    RenderKitUtils.attributes().generic("onchange", "onchange", "change", "valueChange").first()));
075        }
076        String onchange = convertToString(RenderKitUtils.getAttributeAndBehaviorsValue(context, component,
077                RenderKitUtils.attributes().generic("onchange", "onchange", "change", "valueChange").first()));
078        if (targetOnchange != null && !targetOnchange.trim().isEmpty()) {
079            onchange = onchange == null ? targetOnchange : targetOnchange + ";" + onchange;
080        }
081        if (onchange != null && onchange.trim().length() > 0) {
082            writer.writeAttribute("onchange", onchange, "onchange");
083        }
084        getUtils().encodeAttributesFromArray(
085                context,
086                component,
087                new String[] { "accept", "accesskey", "align", "alt", "checked", "dir", "disabled", "lang",
088                        "maxlength", "onblur", "onclick", "ondblclick", "onfocus", "onkeydown", "onkeypress",
089                        "onkeyup", "onmousedown", "onmousemove", "onmouseout", "onmouseover", "onmouseup", "onselect",
090                        "readonly", "size", "src", "style", "tabindex", "title", "usemap", "xml:lang" });
091
092        writer.endElement("input");
093        writer.startElement("label", component);
094        writer.writeAttribute("for", clientId, "for");
095        writer.writeText(convertToString(item.getLabel()), null);
096        writer.endElement("label");
097    }
098
099    @Override
100    protected Class<? extends UIComponent> getComponentClass() {
101        return UIRadio.class;
102    }
103
104    private boolean isDisabled(UIComponent targetComponent) {
105        if (targetComponent instanceof HtmlSelectOneRadio) {
106            return ((HtmlSelectOneRadio) targetComponent).isDisabled();
107        } else {
108            final Object disabled = targetComponent.getAttributes().get("disabled");
109            return Boolean.TRUE.equals(disabled);
110        }
111    }
112
113    private boolean isReadonly(UIComponent targetComponent) {
114        if (targetComponent instanceof HtmlSelectOneRadio) {
115            return ((HtmlSelectOneRadio) targetComponent).isReadonly();
116        } else {
117            final Object readonly = targetComponent.getAttributes().get("readonly");
118            return Boolean.TRUE.equals(readonly);
119        }
120    }
121}