| /* |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| */ |
| package org.apache.myfaces.trinidadinternal.renderkit.core.xhtml; |
| |
| import java.io.IOException; |
| |
| import java.util.Map; |
| |
| import javax.faces.component.UIComponent; |
| import javax.faces.context.FacesContext; |
| import javax.faces.context.ResponseWriter; |
| |
| import org.apache.myfaces.trinidad.bean.FacesBean; |
| import org.apache.myfaces.trinidad.bean.PropertyKey; |
| import org.apache.myfaces.trinidad.component.UIXGroup; |
| import org.apache.myfaces.trinidad.component.UIXPanel; |
| import org.apache.myfaces.trinidad.component.html.HtmlTableLayout; |
| import org.apache.myfaces.trinidad.context.Agent; |
| import org.apache.myfaces.trinidad.context.FormData; |
| import org.apache.myfaces.trinidad.context.RenderingContext; |
| import org.apache.myfaces.trinidad.context.RequestContext; |
| import org.apache.myfaces.trinidadinternal.renderkit.core.xhtml.table.TableRenderingContext; |
| |
| |
| /** |
| * @todo Support "end" facet??? |
| */ |
| public abstract class LabelAndMessageRenderer extends XhtmlRenderer |
| { |
| static public final String INLINE_MESSAGE_DEFAULT_GAP = "12"; |
| static public final String INLINE_MESSAGE_PDA_GAP = "2"; |
| |
| public LabelAndMessageRenderer( |
| FacesBean.Type type) |
| { |
| super(type); |
| } |
| |
| @Override |
| public boolean getRendersChildren() |
| { |
| return true; |
| } |
| |
| @Override |
| protected void findTypeConstants( |
| FacesBean.Type type) |
| { |
| super.findTypeConstants(type); |
| |
| _labelKey = type.findKey("label"); |
| _requiredKey = type.findKey("required"); |
| _showRequiredKey = type.findKey("showRequired"); |
| |
| _message = new Message(type); |
| _label = new Label(type, false); |
| _labelInTable = new Label(type, true); |
| } |
| |
| private boolean _needsTableTag( |
| UIComponent component) |
| { |
| // Find the first content-generating parent |
| UIComponent parent = XhtmlUtils.getStructuralParent(component); |
| if (parent == null) |
| return true; |
| |
| // =-=AEW We should review this code. |
| // Either the parent should mark down that it rendered |
| // a table, or we should lean on the ResponseWriter |
| // to tell us if a table had been used. |
| |
| // Hardcoding some packages 'cause I need this code to change! |
| String family = parent.getFamily(); |
| if (HtmlTableLayout.COMPONENT_FAMILY.equals(family)) |
| { |
| return false; |
| } |
| |
| return true; |
| } |
| |
| private boolean _isParentPanelForm( |
| FacesContext context, |
| UIComponent component) |
| { |
| if (PanelFormLayoutRenderer.__isInPanelFormLayout(context, component)) |
| { |
| return true; |
| } |
| |
| // We must know if the immediate parent is a PanelForm because if there is |
| // even just one other component inbetween this component and a PanelForm, |
| // we must render different DOM--the same DOM as if there were no parent |
| // PanelForm. |
| UIComponent parentComponent = component.getParent(); |
| String family = parentComponent.getFamily(); |
| // FIXME: OK... This is another strong coupling |
| // We could add a an interface instead like ComponentHolder or something |
| // instead of checking against a specific component family. |
| while (UIXGroup.COMPONENT_FAMILY.equals(family)) |
| { |
| // Special case: |
| // Since UIXGroup components are purely organizational, it is valid to |
| // have them inbetween panelForm-friendly components and the panelForm, |
| // so we need to look further up the chain: |
| parentComponent = parentComponent.getParent(); |
| if (parentComponent == null) |
| { |
| return false; |
| } |
| family = parentComponent.getFamily(); |
| } |
| if (UIXPanel.COMPONENT_FAMILY.equals(family)) |
| { |
| String rendererType = parentComponent.getRendererType(); |
| if (_isFormRendererType(rendererType)) |
| return true; |
| } |
| return false; |
| } |
| |
| /** |
| * Retrieves whether the labels should be rendered above fields as opposed to |
| * the side of the fields. |
| * @param context the Faces context |
| * @param needsPanelFormLayout true if using a panelFormLayout |
| * @return true if labels are stacked above fields |
| */ |
| private boolean _isLabelStartAligned( |
| FacesContext context, |
| boolean needsPanelFormLayout) |
| { |
| // For narrow-screen PDAs, always render the Label above fields. |
| if (supportsNarrowScreen(RenderingContext.getCurrentInstance())) |
| return false; |
| |
| if (needsPanelFormLayout) |
| { |
| Map requestMap = context.getExternalContext().getRequestMap(); |
| Object labelsStartAligned = requestMap.get( |
| PanelFormLayoutRenderer.PANEL_FORM_LAYOUT_LABELS_START_ALIGNED_KEY); |
| return Boolean.TRUE.equals(labelsStartAligned); |
| } |
| return true; |
| } |
| |
| // Put the outer style class here, like af_selectManyRadio, styleClass, |
| // inlineStyle, 'state' styles like p_AFDisabled, etc. |
| protected void renderRootDomElementStyles( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean |
| ) throws IOException |
| { |
| // do nothing for now |
| } |
| |
| @Override |
| protected boolean shouldRenderId( |
| FacesContext context, |
| UIComponent component) |
| { |
| return true; |
| } |
| |
| private boolean _isInTable() |
| { |
| TableRenderingContext tContext = |
| TableRenderingContext.getCurrentInstance(); |
| if (tContext != null) |
| { |
| return TableRenderingContext.isInsideContentOfTable(); |
| } |
| |
| return false; |
| } |
| |
| /** |
| */ |
| @Override |
| protected void encodeAll( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean |
| ) throws IOException |
| { |
| String clientId = component.getClientId(context); |
| |
| // If we're a leaf component, see if we can skip our rendering |
| if (isLeafRenderer() && canSkipRendering(rc, clientId)) |
| { |
| // Except we really do have a "help" facet, so render that one... |
| UIComponent help = getFacet(component, "help"); |
| if (help != null) |
| encodeChild(context, help); |
| return; |
| } |
| |
| String saved = rc.getCurrentClientId(); |
| rc.setCurrentClientId(clientId); |
| |
| boolean isInTable = _isInTable(); |
| |
| if (hasOwnLabel(component, bean) || isInTable) |
| { |
| String value = getLabel(component, bean); |
| FormData fd = rc.getFormData(); |
| if (fd != null) |
| fd.addLabel(clientId, value); |
| } |
| |
| RequestContext requestContext = RequestContext.getCurrentInstance(); |
| boolean needsPanelFormLayout = _isParentPanelForm(context, component); |
| boolean isInline = (requestContext.getClientValidation() == |
| RequestContext.ClientValidation.INLINE); |
| if (isInTable && !needsPanelFormLayout) |
| { |
| ResponseWriter rw = context.getResponseWriter(); |
| delegateRenderer(context, rc, component, bean, _labelInTable); |
| renderFieldCellContents(context, rc, component, bean); |
| |
| if (isInline || hasMessage(context, rc, component, bean)) |
| { |
| rw.startElement("div", null); |
| rw.endElement("div"); |
| _renderMessageCellContents(context, rc, component, bean); |
| } |
| |
| // In the case of narrow-screen PDAs, to reduce the component's width, |
| // End facet is always rendered below. |
| renderEndFacetForNarrowPDA(context, rc, component, true); |
| } |
| else |
| { |
| ResponseWriter rw = context.getResponseWriter(); |
| boolean isLabelStartAligned = _isLabelStartAligned(context, |
| needsPanelFormLayout); |
| |
| // need a table if |
| // 1) panelForm-friendly component with stacked prompt |
| // 2) not a non-panelForm-friendly component |
| boolean needsTableTag = !isLabelStartAligned || |
| (!needsPanelFormLayout && _needsTableTag(component)); |
| |
| boolean isPIE = Agent.PLATFORM_PPC.equalsIgnoreCase( |
| rc.getAgent().getPlatformName()); |
| |
| if (needsTableTag) |
| { |
| // While handling a PPR response, Windows Mobile cannot DOM replace |
| // a table element. Wrapping a table element with a div element fixes |
| // the problem. |
| if (isPIE) |
| { |
| rw.startElement("div", component); |
| renderId(context, component); |
| rw.startElement("table", null); |
| } |
| else |
| { |
| rw.startElement("table", component); |
| } |
| |
| // =-=AEW THIS DOESN'T SEEM RIGHT - IT SHOULD GO ON THE INPUT FIELD |
| // ONLY, RIGHT? Matching UIX 2.2 behavior here. |
| rw.writeAttribute("title", getShortDesc(component, bean), "title"); |
| if (!isDesktop(rc)) |
| { |
| // On PDA browsers label and message pair is always |
| // rendered in full width. |
| rw.writeAttribute("width", "100%", null); |
| } |
| |
| if (!isPIE) |
| renderId(context, component); |
| |
| // put the outer style class here, like af_inputText, styleClass, |
| // inlineStyle, 'state' styles like p_AFDisabled, etc. |
| renderRootDomElementStyles(context, rc, component, bean); |
| |
| OutputUtils.renderLayoutTableAttributes(context, rc, "0", null); |
| } |
| |
| rw.startElement("tr", null); |
| |
| if (!needsTableTag) |
| { |
| // Render the ID or else the component cannot be PPR-ed in a future update (both the label |
| // its associated icons, and the field should update if this component is PPR-ed): |
| renderId(context, component); |
| |
| // -= Simon =- HACK |
| // It's ugly, I hate it, but it works and it's better than pushing |
| // Cannot use a span either because td is not a valid span child. |
| //rw.startElement("td", component); |
| //rw.startElement("table", component); |
| //OutputUtils.renderLayoutTableAttributes(context, rc, "0", null); |
| //rw.startElement("tbody", component); |
| //rw.startElement("tr", component); |
| //renderRootDomElementStyles(context, rc, component, bean); |
| |
| // Basically, we're screwed unless we specify panelForm to keep a |
| // class-less container opened to receive the rootDomStyles. |
| // Even if this is the case we need a way to detect if a new |
| // element get opened from encodeBetweenLabelAndFieldCells call. |
| // Since the above option is so ugly, I'll assume that. |
| // FIXME: That's too strongly coupled to my taste. Even being stuck |
| // with a parent tr is too strongly coupled to my taste. |
| renderRootDomElementStyles(context, rc, component, bean); |
| } |
| |
| boolean labelExists = (getLabel(component, bean) != null); |
| |
| _renderLabelCell(context, rc, component, bean, labelExists); |
| |
| if (!isLabelStartAligned) |
| { |
| rw.endElement("tr"); |
| rw.startElement("tr", null); |
| } |
| |
| //This part is necessary to make work hspace on tr:tableFormLayout |
| Map<String, Object> requestMap = context.getExternalContext() |
| .getRequestMap(); |
| |
| Integer hspaceObject = (Integer) requestMap.get( |
| "org.apache.myfaces.trinidadinternal.TableFormHspace"); |
| |
| Boolean percentWidthObject = (Boolean) requestMap.get( |
| "org.apache.myfaces.trinidadinternal.TableFormPercentWidth"); |
| |
| if (hspaceObject != null) |
| { |
| rw.startElement("td", null); |
| if (percentWidthObject != null && percentWidthObject == true) |
| { |
| rw.writeAttribute("width", hspaceObject +"%", null); |
| } |
| else |
| { |
| rw.writeAttribute("width", hspaceObject, null); |
| } |
| rw.endElement("td"); |
| } |
| |
| _renderFieldCell(context, rc, component, bean, labelExists, needsPanelFormLayout, isInline); |
| |
| rw.endElement("tr"); |
| |
| // End encoding of the non-panelForm-friendly wrappers: |
| if (!needsPanelFormLayout) |
| { |
| if (isInline || hasMessage(context, rc, component, bean)) |
| { |
| rw.startElement("tr", null); |
| if (isLabelStartAligned) |
| { |
| // We need an empty cell to prevent the label from spanning down into the footer area and |
| // to make sure the footer appears below the field cell. |
| rw.startElement("td", null); |
| rw.endElement("td"); |
| } |
| |
| rw.startElement("td", null); |
| renderStyleClass(context, rc, |
| SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS); |
| _renderMessageCellContents(context, rc, component, bean); |
| rw.endElement("td"); |
| |
| rw.endElement("tr"); |
| } |
| } |
| |
| // In the case of narrow-screen PDAs, to reduce the component's width, |
| // End facet is always rendered below. |
| renderEndFacetForNarrowPDA(context, rc, component, false); |
| |
| if (needsTableTag) |
| { |
| rw.endElement("table"); |
| |
| if (isPIE) |
| rw.endElement("div"); |
| } |
| } |
| |
| rc.setCurrentClientId(saved); |
| } |
| |
| // subclasses should override this |
| protected String getRootStyleClass( |
| UIComponent component, |
| FacesBean bean) |
| { |
| return null; |
| } |
| |
| /** |
| * @todo Get cell alignment from skin property. |
| */ |
| private void _renderLabelCell( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean, |
| boolean labelExists |
| ) throws IOException |
| { |
| ResponseWriter rw = context.getResponseWriter(); |
| rw.startElement("td", null); |
| |
| // render labelStyleClass and defaultStyleClass. |
| renderStyleClasses(context, rc, new String[] |
| { |
| getLabelStyleClass(component, bean), |
| _getDefaultLabelStyleClass(rc, SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS) |
| }); |
| |
| String labelInlineStyle = getLabelInlineStyleKey(component, bean); |
| |
| // In the case of narrow-screen PDAs, the Label is rendered above fields. |
| // So Label should be left aligned to be in align with fields below. |
| if (supportsNarrowScreen(rc)) |
| { |
| labelInlineStyle = labelInlineStyle + ";text-align: left;"; |
| } |
| |
| rw.writeAttribute("style", labelInlineStyle, null); |
| |
| String valign = getDefaultLabelValign(component, bean); |
| |
| rw.writeAttribute("valign", valign, null); |
| if (isDesktop(rc)) |
| { |
| // On PDA browsers where width is limited, the label is allowed to wrap. |
| rw.writeAttribute("nowrap", Boolean.TRUE, null); |
| } |
| |
| if (labelExists) |
| { |
| rw.writeAttribute("width", |
| rc.getProperties().get(_LABEL_CELL_WIDTH_KEY), |
| null); |
| } |
| |
| delegateRenderer(context, rc, component, bean, _label); |
| rw.endElement("td"); |
| } |
| |
| /** |
| * @todo see if bug 2484841 still applies! |
| */ |
| private void _renderFieldCell( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean, |
| boolean labelExists, |
| boolean needsPanelFormLayout, |
| boolean isInline |
| ) throws IOException |
| { |
| ResponseWriter rw = context.getResponseWriter(); |
| rw.startElement("td", null); |
| |
| rw.writeAttribute("valign", "top", null); |
| if (isDesktop(rc)) |
| { |
| // On PDA browsers where width is limited, the field data is |
| // allowed to wrap. |
| rw.writeAttribute("nowrap", Boolean.TRUE, null); |
| } |
| |
| renderStyleClass(context, rc, SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS ); |
| |
| if (labelExists) |
| rw.writeAttribute("width", |
| rc.getProperties().get(_FIELD_CELL_WIDTH_KEY), |
| null); |
| |
| renderFieldCellContents(context, rc, component, bean); |
| |
| // The panelForm places messages below the fields, not on a separate |
| // row: |
| if (needsPanelFormLayout) |
| { |
| // =-= mcc PPR PROBLEM!!! We should always be rendering the "div", |
| // and always rendering an ID, if we ever want it to be PPR |
| // replaceable: |
| if (isInline || hasMessage(context, rc, component, bean)) |
| { |
| rw.startElement("div", null); |
| renderStyleClass(context, rc, |
| SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS); |
| _renderMessageCellContents(context, rc, component, bean); |
| rw.endElement("div"); |
| } |
| } |
| |
| // bug 2484841: PDA: TOO MUCH WHITESPACE BETWEEN |
| // INPUT ELEMENTS IN LABELEDFIELD |
| // This is a browser bug workaround, hopefully we can remove it eventually |
| if (isPDA(rc) && isIE(rc)) |
| { |
| rw.startElement("div", null); |
| renderSpacer(context, rc, "1", "0"); |
| rw.endElement("div"); |
| } |
| |
| rw.endElement("td"); |
| } |
| |
| static String __getCachedClientId( |
| RenderingContext rc) |
| { |
| String clientId = rc.getCurrentClientId(); |
| assert(clientId != null); |
| return clientId; |
| } |
| |
| protected String getFieldCellContentsStyleClass( |
| UIComponent component, |
| FacesBean bean) |
| { |
| // Override if you want a "af_panelLabelAndMessage_content" style class |
| return null; |
| } |
| |
| protected String getFooterContentsStyleClass( |
| UIComponent component, |
| FacesBean bean) |
| { |
| // Override if you want a style class for the footer container |
| return null; |
| } |
| |
| protected boolean hasMessage( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean) |
| { |
| UIComponent help = getFacet(component, "help"); |
| if (help != null) |
| return true; |
| |
| String id = getLabelFor(context, rc, component, bean); |
| return context.getMessages(id).hasNext(); |
| } |
| |
| private void _renderMessageCellContents( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean) |
| throws IOException |
| { |
| delegateRenderer(context, rc, component, bean, _message); |
| } |
| |
| /** |
| * Returns the client ID. |
| */ |
| @Override |
| protected String getClientId( |
| FacesContext context, |
| UIComponent component) |
| { |
| return (super.getClientId(context, component) + |
| XhtmlConstants.COMPOSITE_ID_EXTENSION); |
| } |
| |
| protected boolean isLeafRenderer() |
| { |
| return true; |
| } |
| |
| protected String getDefaultLabelValign( |
| UIComponent component, |
| FacesBean bean) |
| { |
| return null; |
| } |
| |
| abstract protected void renderFieldCellContents( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean |
| ) throws IOException; |
| |
| /** |
| * Renders footer contents if isFooterPresent() is true. |
| * @param context the FacesContext |
| * @param rc the RenderingContext |
| * @param component the component to render |
| * @param bean the FacesBean of the component to render |
| * @throws IOException if there are problems rendering the contents |
| */ |
| protected void renderFieldFooterContents( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean |
| ) throws IOException |
| { |
| // render nothing by default |
| } |
| |
| /** |
| * If it's known that the field content is not editable, return false. |
| * Otherwise, assume it is editable and return true |
| */ |
| protected boolean isContentEditable( |
| UIComponent component, |
| FacesBean bean) |
| { |
| return true; |
| } |
| |
| protected boolean isIndented() |
| { |
| return false; |
| } |
| |
| /** |
| * Override and return "true" to indicate that the component |
| * has its own internal label - and that therefore there |
| * shouldn't be an HTML <label> tag, for instance. |
| */ |
| protected boolean hasOwnLabel( |
| UIComponent component, |
| FacesBean bean) |
| { |
| return false; |
| } |
| |
| protected boolean showAccessKeyOnLabel( |
| UIComponent component, |
| FacesBean bean) |
| { |
| // By default, if we have our own label, don't show the |
| // access key on the label (but that's not always true) |
| return !hasOwnLabel(component, bean); |
| } |
| |
| /** |
| * Returns the ID (clientId) of the component that |
| * should receive the label. |
| */ |
| abstract protected String getLabelFor( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean); |
| |
| static void __setLabelWidth( |
| RenderingContext rc, |
| Object width) |
| { |
| rc.getProperties().put(_LABEL_CELL_WIDTH_KEY, width); |
| } |
| |
| static void __setFieldWidth( |
| RenderingContext rc, |
| Object width) |
| { |
| rc.getProperties().put(_FIELD_CELL_WIDTH_KEY, width); |
| } |
| |
| static void __clearProperties( |
| RenderingContext rc) |
| { |
| rc.getProperties().remove(_LABEL_CELL_WIDTH_KEY); |
| rc.getProperties().remove(_FIELD_CELL_WIDTH_KEY); |
| } |
| |
| private class Label extends OutputLabelRenderer |
| { |
| public Label( |
| FacesBean.Type type, |
| boolean inTable) |
| { |
| super(type); |
| _inTable = inTable; |
| } |
| |
| @Override |
| protected boolean shouldRenderId( |
| FacesContext context, |
| UIComponent component) |
| { |
| return false; |
| } |
| |
| @Override |
| protected boolean needComponentInStartElement() |
| { |
| // Because we're not rendering the ID on the label (at this time) |
| // there's no point in passing the component to startElement() - it |
| // just makes PPR unhappy to do so |
| return false; |
| } |
| |
| @Override |
| protected void renderAllAttributes( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean |
| ) throws IOException |
| { |
| // Block everything |
| } |
| |
| @Override |
| protected String getDefaultValign( |
| UIComponent component, |
| FacesBean bean) |
| { |
| // get the defaultLabelValign from the form component. |
| return getDefaultLabelValign(component, bean); |
| } |
| |
| @Override |
| protected String getConvertedString( |
| FacesContext context, |
| UIComponent component, |
| FacesBean bean) |
| { |
| if (_inTable) |
| return null; |
| |
| return LabelAndMessageRenderer.this.getLabel(component, bean); |
| } |
| |
| /** |
| * Only display the required icon indicator if we're required |
| * or showRequired is on. |
| */ |
| @Override |
| protected boolean getShowRequired( |
| UIComponent component, |
| FacesBean bean) |
| { |
| // Inside the table, never show the required icon. |
| if (_inTable) |
| return false; |
| |
| return (LabelAndMessageRenderer.this.labelShowRequired(component, bean)); |
| } |
| |
| @Override |
| protected char getAccessKey( |
| UIComponent component, |
| FacesBean bean) |
| { |
| if (LabelAndMessageRenderer.this.showAccessKeyOnLabel(component, bean)) |
| return super.getAccessKey(component, bean); |
| |
| return CHAR_UNDEFINED; |
| } |
| |
| @Override |
| protected String getShortDesc( |
| UIComponent component, |
| FacesBean bean) |
| { |
| String shortDesc = super.getShortDesc(component, bean); |
| // =-=AEW Apparently, we're supposed to do this |
| // for screenReader selectOneRadio and selectBooleanRadio!?! |
| if ((shortDesc == null) && _inTable) |
| { |
| shortDesc = LabelAndMessageRenderer.this.getLabel(component, bean); |
| } |
| |
| return shortDesc; |
| } |
| |
| @Override |
| protected String getForId( |
| FacesContext context, |
| UIComponent component, |
| FacesBean bean) |
| { |
| return getLabelFor(context, |
| RenderingContext.getCurrentInstance(), |
| component, |
| bean); |
| } |
| |
| @Override |
| protected boolean isLabelTagNeeded( |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean, |
| String forId, |
| int accessKeyIndex |
| ) |
| { |
| if (LabelAndMessageRenderer.this.hasOwnLabel(component, bean)) |
| return false; |
| |
| return super.isLabelTagNeeded(rc, component, bean, forId, accessKeyIndex); |
| } |
| |
| private final boolean _inTable; |
| } |
| |
| private class Message extends MessageRenderer |
| { |
| public Message( |
| FacesBean.Type type) |
| { |
| super(type); |
| } |
| |
| @Override |
| protected boolean shouldRenderId( |
| FacesContext context, |
| UIComponent component) |
| { |
| return false; |
| } |
| |
| @Override |
| protected String getShortDesc( |
| UIComponent component, |
| FacesBean bean) |
| { |
| return null; |
| } |
| |
| @Override |
| protected boolean getIndented( |
| UIComponent component, |
| FacesBean bean) |
| { |
| return LabelAndMessageRenderer.this.isIndented(); |
| } |
| |
| @Override |
| protected void renderAllAttributes( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| FacesBean bean |
| ) throws IOException |
| { |
| } |
| |
| @Override |
| protected String getForId( |
| FacesContext context, |
| UIComponent component, |
| FacesBean bean) |
| { |
| return getLabelFor(context, |
| RenderingContext.getCurrentInstance(), |
| component, |
| bean); |
| } |
| } |
| |
| protected String getLabelInlineStyleKey( |
| UIComponent component, |
| FacesBean bean) |
| { |
| return null; // overridden by PanelLabelAndMessageRenderer |
| } |
| |
| /** |
| * Hook for resolving whether we should show the "required" icon. |
| */ |
| protected boolean labelShowRequired( |
| UIComponent component, |
| FacesBean bean) |
| { |
| // If we're required (from the input side of things), |
| // or showRequired is true, then show the "required" icon. |
| // Unless we're read-only, in which case never show it. |
| if (getRequired(component, bean) || getShowRequired(component, bean)) |
| { |
| return isContentEditable(component, bean); |
| } |
| |
| return false; |
| } |
| |
| protected boolean getShowRequired( |
| UIComponent component, |
| FacesBean bean) |
| { |
| if(_showRequiredKey == null) |
| { // showRequired is not supporte on the element |
| return false; |
| } |
| |
| Object o = bean.getProperty(_showRequiredKey); |
| if (o == null) |
| { |
| o = _showRequiredKey.getDefault(); |
| } |
| |
| return Boolean.TRUE.equals(o); |
| } |
| |
| protected boolean getRequired( |
| UIComponent component, |
| FacesBean bean) |
| { |
| Object o = bean.getProperty(_requiredKey); |
| if (o == null) |
| o = _requiredKey.getDefault(); |
| |
| return Boolean.TRUE.equals(o); |
| } |
| |
| protected String getLabel( |
| UIComponent component, |
| FacesBean bean) |
| { |
| return toString(bean.getProperty(_labelKey)); |
| } |
| |
| /** |
| * This gets the rootStyleClass from the bean, appends ::label to it, |
| * @param bean |
| * @return |
| */ |
| protected String getLabelStyleClass( |
| UIComponent component, |
| FacesBean bean) |
| { |
| String styleClass = getRootStyleClass(component, bean); |
| if(styleClass != null) |
| { |
| styleClass += _LABEL_PSEUDO_ELEMENT; |
| } |
| |
| return styleClass; |
| } |
| |
| /* This method is responsible for rendering the End facet for narrow-screen |
| * PDAs. In the case of narrow-screen PDAs, End facet is rendered after the |
| * Help facet as shown below |
| * +------+ |
| * |Label | |
| * +------+ |
| * |Field | |
| * +----------+ |
| * |Help facet| |
| * +----------+ |
| * |End facet | |
| * ------------ |
| * @param context a <code>FacesContext</code> |
| * @param arc a <code>RenderingContext</code> |
| * @param component a <code>UIComponent</code> the component to render |
| * @param insideTableData a <code>boolean</code> indicates whether End |
| * Facet to be rendered is in inside a table data(<TD>) |
| * @throws IOException if there are problems in rendering contents |
| */ |
| |
| protected void renderEndFacetForNarrowPDA( |
| FacesContext context, |
| RenderingContext rc, |
| UIComponent component, |
| boolean insideTableData) |
| throws IOException |
| { |
| // Nothing by default. Applicable only for the |
| // components that support End facet. |
| } |
| |
| // If we have mapped this style (like in panelForm), |
| // then return the style, otherwise return null |
| private String _getDefaultLabelStyleClass( |
| RenderingContext rc, |
| String styleClass) |
| { |
| Map<String, String> keyMap = rc.getSkinResourceKeyMap(); |
| return (keyMap != null) ? |
| keyMap.get(styleClass) : |
| null; |
| } |
| |
| private boolean _isFormRendererType(String rendererType) |
| { |
| return "org.apache.myfaces.trinidad.Form".equals(rendererType) || |
| "org.apache.myfaces.trinidad.FormLayout".equals(rendererType) || |
| "org.apache.myfaces.trinidad.rich.Form".equals(rendererType) || |
| "org.apache.myfaces.trinidad.TableLayout".equals(rendererType); |
| } |
| |
| |
| // THESE VALUES MUST MATCH THOSE IN INLINEMESSAGERENDERER |
| // (at least for as long as both classes exist) |
| static private final Object _LABEL_CELL_WIDTH_KEY = "_imLCWidth"; |
| static private final Object _FIELD_CELL_WIDTH_KEY = "_imFCWidth"; |
| |
| private static final String _LABEL_PSEUDO_ELEMENT = "::label"; |
| |
| private PropertyKey _labelKey; |
| private PropertyKey _requiredKey; |
| private PropertyKey _showRequiredKey; |
| private XhtmlRenderer _message; |
| private XhtmlRenderer _label; |
| private XhtmlRenderer _labelInTable; |
| } |