You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@myfaces.apache.org by Matt Cooper <ma...@gmail.com> on 2007/06/04 21:11:23 UTC

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

I think decoupling of these renderers would be a good thing.  The trick will
be to make sure the form item renders properly when it is a direct child of
the form layout component.  Let's say that you put a tr:panelGroupLayout (or
some other non form layout component) inbetween the form layout component
and the form item--I feel that that particular form item should render the
same as if there was no form layout involved (this would be insulating the
form item from the form layout).

When considering a decoupling approach, you will also want consider cases
where a developer wants to have one kind of a form layout component inside
of another form layout component.  There will need to be some sort of
mechanism to ensure the correct rendering path is taken for the each
particular component hierarchy so a simple "am I contained, at any level, in
a form layout" might not be sufficient but an "am I a direct child of a form
layout" might.

Today, I believe if you have a tr:panelFormLayout inside of another
tr:panelFormLayout, the outer layout will have labels on the side of the
contents and the inner layout will have the labels above the contents.  This
is determined by a request attribute that is present only during the
encodeAll of the PanelFormLayout's encoding.

One final tip...  There is one particular case where a form item isn't a
direct child of the form layout but will still render as a form item:  when
it is contained in a tr:group component and that tr:group is a direct child
of the form layout.  The tr:group component is used by the form layout
renderer to draw separator lines between groups of form items.

Regards,
Matt

On 5/24/07, Leonardo Uribe <lu...@gmail.com> wrote:
>
> Hi everybody.
>
> I'm working on a trinidad component for do layout (as part of a Google
> Summer of Code) more easy and with less code than panelFormLayout
> component.
>
> Checking the code, I found a strong coupling between the classes
> PanelFormLayoutRenderer and LabelAndMessageRenderer.
>
> I found the following points:
>
> 1. LabelAndMessageRenderer has about 3 behaviors, depending what is his
> parent components. In the code it checks in a method something like
> that:
>
>   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) ;
>   }
>
> Because my component is a new component, i have to add a line like this
>
>     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);
>
> But this is very hacky. I have to do this because i need that the method
> in encodeAll of LabelAndMessageRenderer
>
> boolean needsPanelFormLayout = _isParentPanelForm(component);
>
> returns true, because my component layout a table like panelFormLayout.
>
> 2. In other part of the code, LabelAndMessageRenderer call this method (in
> encodeAll)
>
>       if (needsPanelFormLayout)
>       {
>         if(PanelFormLayoutRenderer.encodeBetweenLabelAndFieldCells(context,
> arc, rw))
>         {
>           renderRootDomElementStyles(context, arc, component, bean);
>         }
>       }
>
> What if my component has another behavior to this method?
> PanelFormLayoutRenderer detects if this panelFormLayout is inside
> another panelFormLayout and because if it is the case, it adds between
> Label and Field Cells something like this
>
>       rw.endElement("tr"); // label row
>       rw.startElement("tr", null); // field row
>
> So, the label is rendered on top of the field.
>
> 3. LabelAndMessageRenderer do this for render a Label an a field (please
> look the parts in yellow)
>
>   private void _renderLabelCell(
>     FacesContext        context,
>     RenderingContext arc,
>     UIComponent         component,
>     FacesBean           bean,
>     boolean             labelExists) throws IOException
>   {
>     ResponseWriter rw = context.getResponseWriter();
>     rw.startElement("td", null);
>
>     // render labelStyleClass and defaultStyleClass.
>     renderStyleClasses(context, arc, new String[]{
>                        getLabelStyleClass(bean),
>                        _getDefaultLabelStyleClass(arc,
>                           SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS )});
>
>     String labelInlineStyle = getLabelInlineStyleKey(bean);
>     rw.writeAttribute("style", labelInlineStyle, null);
>
>     String valign = getDefaultLabelValign(bean);
>
>     rw.writeAttribute ("valign", valign, null);
>     if (isDesktop(arc))
>       rw.writeAttribute("nowrap", Boolean.TRUE, null);
>
>     if (labelExists)
>     {
>       rw.writeAttribute("width",
>                         arc.getProperties().get(_LABEL_CELL_WIDTH_KEY),
>                         null);
>     }
>
>     delegateRenderer(context, arc, component, bean, _label);
>     rw.endElement ("td");
>   }
>
>   private void _renderFieldCell(
>     FacesContext        context,
>     RenderingContext arc,
>     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);
>     rw.writeAttribute("nowrap", Boolean.TRUE, null);
>
>     renderStyleClass(context, arc,
> SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS );
>
>     if (labelExists)
>       rw.writeAttribute("width",
>                         arc.getProperties().get(_FIELD_CELL_WIDTH_KEY),
>                         null);
>
>     renderFieldCellContents(context, arc, 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, arc, component, bean))
>       {
>         rw.startElement("div", null);
>         renderStyleClass(context, arc,
>
> SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS);
>         _renderMessageCellContents(context, arc, 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(arc) && isIE(arc))
>     {
>       rw.startElement("div", null);
>       renderSpacer(context, arc, "1", "0");
>       rw.endElement("div");
>     }
>
>     rw.endElement("td");
>   }
>
> I need to add an attribute in the td tag like <td colspan=2 rowspan=3
> height=XXX width=XXX .........>, but if i want this, i need to
> modify LabelAndMessageRenderer to recognize if the parent component is my
> component, check if it has an attribute like this
>
>                     <mycomp:tableFormLayout labelWidth="100"  width="400"
> height="300"
>                         fieldWidth="100" rows="100" columns="1*;1*;1*" >
>                         <tr:selectOneChoice label="Salutation">
>                             <f:selectItem itemLabel="1 Option"
> itemValue="1" />
>                             <f:attribute name="spanXItem" value="2"/>
>                             <f:attribute name="spanYItem" value="3"/>
>                         </tr:selectOneChoice>
>                     </mycomp:tableFormLayout>
>
> and finally add a colspan or rowspan (height and width are optional).
>
> ---------
> Conclusion?: It's necesary to decouple PanelFormLayoutRenderer and other
> FormRenderers with LabelAndMessageRenderer in order to avoid
> those hacks. I propose to create an interface that implements some
> affected methods or create new ones, and delegate this rendering to the
> parent
> classes.
>
> I want to you what should be better to do in that case. If its necesary to
> refactor the classes, how it can be done.
>
> Thanks for your attention
>
> regards
>
> Att: Leonardo Uribe
> Ingeniero de Sistemas
> Pontificia Universidad Javeriana
> Ingeniero Electronico
> Universidad Nacional de Colombia
>
>
>
>
>
>
>
>

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Adam Winer <aw...@gmail.com>.
Sorry I haven't been able to help here - this would be great
work, but it's also non-trivial, and I haven't had the time
to help out.  Can any of the other committers help
Leonardo out?

-- Adam


On 8/8/07, Leonardo Uribe <lu...@gmail.com> wrote:
> Any suggestions about refactoring some trinidad components?
>

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Leonardo Uribe <lu...@gmail.com>.
Any suggestions about refactoring some trinidad components?

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Leonardo Uribe <lu...@gmail.com>.
Hi

Previously, I have tried to separate PanelFormLayoutRenderer and
LabelAndMessageRenderer (From this
renderer inherits all components that have a label attribute, almost all
components). I have added some methods
in RenderingContext to manage a RenderDescriptor class, and using a proper
interface creating a class that inherits
RenderDescriptor and implement the interface to let the parent component
render some details of its children.

This point of view is good, and in the practice works (I have rewrite the
two rendererers using this and
it works good), but I feel there is something wrong with this solution.
Thinking more in this topic I have
found some things that makes me change of opinion. The big problem is not
decouple two renderer, the problem
is that LabelAndMessageRenderer do a diferent enclosing HTML tags for a
component that has a Renderer that
extends from this renderer.
A component that is renderer by this renderer, check if it is inside a
panelFormLayout, or inside a table, or its surrounded
by non friendly container components and in each case do something
different.

Would have a component to know about its surroundings to do his html tags?
(probably adding more complexity doing
what I say on the first paragraph)

Or

it could be better that the surrounding components adds proper html tags to
render the enclosing tags for a type of component
or another, in order to avoid this strong coupling? (Simpler, but it needs
to do a rewrite of some components in trinidad).

What do you think about this?

Suggestions are welcome.

regards

Leonardo Uribe

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Martin Marinschek <ma...@gmail.com>.
Leonardo,

do you have an idea how to go about implementing this? If not, don't
hesitate to ask more.

regards,

Martin

On 6/7/07, Danny Robinson <da...@gmail.com> wrote:
> +1 (non-binding)
>
>
> On 6/6/07, Simon Lessard <si...@gmail.com> wrote:
> > +1 here as well, we had that issue on a project just last week.
> >
> >
> >
> > On 6/6/07, Jeanne Waldman < jeanne.waldman@oracle.com > wrote:
> > > +1 also.
> > >
> > > Matt Cooper wrote:
> > > > +1 on supporting an iterator around form items, I feel that would be
> > > > quite a powerful enhancement
> > > >
> > > > On 6/5/07, *Adam Winer* < awiner@gmail.com <mailto: awiner@gmail.com>>
> > > > wrote:
> > > >
> > > >     On 6/4/07, * Matt Cooper* <matt.faces@gmail.com
> > > >     <mailto: matt.faces@gmail.com>> wrote:
> > > >
> > > >         I think decoupling of these renderers would be a good thing.
> > > >         The trick will be to make sure the form item renders properly
> > > >         when it is a direct child of the form layout component.  Let's
> > > >         say that you put a tr:panelGroupLayout (or some other non form
> > > >         layout component) inbetween the form layout component and the
> > > >         form item--I feel that that particular form item should render
> > > >         the same as if there was no form layout involved (this would
> > > >         be insulating the form item from the form layout).
> > > >
> > > >
> > > >     One of the big questions to decide when decoupling is whether you
> > > >     want the parent component to augment/enhance the rendering of the
> > > >     children or for the child to be passed more information to render
> > > >     itself differently.  In this case, I wonder if both might be
> > > >     desirable, and I could imagine:
> > > >     - A generic mechanism whereby a parent renderer could say "on my
> > > >     children, here's a CoreRendererDecorator that I'd like to have
> > > >     called for any child CoreRenderer", akin to a servlet fil
> > > >     - A generic mechanism whereby a parent could publish rendering
> > > >     information and child could ask for it, decoupled from looking at
> > > >     the renderer and component (so we don't have getParent() or
> > > >     getParent().getRenderer() and "instanceof" calls), something like
> > > >     Object RenderingContext.getDescriptor(UIComponent parent)?  This'd
> > > >     let us have classes like FormLayoutData in the public API,
> > > >     decoupling the renderers, without forcing us to move the renderers
> > > >     themselves into the public API.
> > > >
> > > >
> > > >         When considering a decoupling approach, you will also want
> > > >         consider cases where a developer wants to have one kind of a
> > > >         form layout component inside of another form layout
> > > >         component.  There will need to be some sort of mechanism to
> > > >         ensure the correct rendering path is taken for the each
> > > >         particular component hierarchy so a simple "am I contained, at
> > > >         any level, in a form layout" might not be sufficient but an
> > > >         "am I a direct child of a form layout" might.
> > > >
> > > >         Today, I believe if you have a tr:panelFormLayout inside of
> > > >         another tr:panelFormLayout, the outer layout will have labels
> > > >         on the side of the contents and the inner layout will have the
> > > >         labels above the contents.  This is determined by a request
> > > >         attribute that is present only during the encodeAll of the
> > > >         PanelFormLayout's encoding.
> > > >
> > > >         One final tip...  There is one particular case where a form
> > > >         item isn't a direct child of the form layout but will still
> > > >         render as a form item:  when it is contained in a tr:group
> > > >         component and that tr:group is a direct child of the form
> > > >         layout.  The tr:group component is used by the form layout
> > > >         renderer to draw separator lines between groups of form items.
> > > >
> > > >
> > > >     And, in addition, I think a lot of people really wish that if you
> > > >     had a tr:iterator inside of
> > > >     a tr:panelFormLayout, that children of that iterator would render
> > > >     as a form item.  I think
> > > >     a CoreRendererDecorator approach might accomplish that...
> > > >
> > > >     -- Adam
> > > >
> > > >
> > > >
> > > >         Regards,
> > > >         Matt
> > > >
> > > >
> > > >         On 5/24/07, *Leonardo Uribe* <lu4242@gmail.com
> > > >         <mailto: lu4242@gmail.com>> wrote:
> > > >
> > > >             Hi everybody.
> > > >
> > > >             I'm working on a trinidad component for do layout (as part
> > > >             of a Google Summer of Code) more easy and with less code
> > > >             than panelFormLayout component.
> > > >
> > > >             Checking the code, I found a strong coupling between the
> > > >             classes PanelFormLayoutRenderer and
> LabelAndMessageRenderer.
> > > >
> > > >             I found the following points:
> > > >
> > > >             1. LabelAndMessageRenderer has about 3 behaviors,
> > > >             depending what is his parent components. In the code it
> > > >             checks in a method something like
> > > >             that:
> > > >
> > > >               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) ;
> > > >               }
> > > >
> > > >             Because my component is a new component, i have to add a
> > > >             line like this
> > > >
> > > >                 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);
> > > >
> > > >             But this is very hacky. I have to do this because i need
> > > >             that the method in encodeAll of LabelAndMessageRenderer
> > > >
> > > >             boolean needsPanelFormLayout =
> _isParentPanelForm(component);
> > > >
> > > >             returns true, because my component layout a table like
> > > >             panelFormLayout.
> > > >
> > > >             2. In other part of the code, LabelAndMessageRenderer call
> > > >             this method (in encodeAll)
> > > >
> > > >                   if (needsPanelFormLayout)
> > > >                   {
> > > >
> > > >
> if(PanelFormLayoutRenderer.encodeBetweenLabelAndFieldCells(context,
> > > >             arc, rw))
> > > >                     {
> > > >
> renderRootDomElementStyles(context, arc,
> > > >             component, bean);
> > > >                     }
> > > >                   }
> > > >
> > > >             What if my component has another behavior to this method?
> > > >             PanelFormLayoutRenderer detects if this panelFormLayout is
> > > >             inside
> > > >             another panelFormLayout and because if it is the case, it
> > > >             adds between Label and Field Cells something like this
> > > >
> > > >                   rw.endElement ("tr"); // label row
> > > >                   rw.startElement("tr", null); // field row
> > > >
> > > >             So, the label is rendered on top of the field.
> > > >
> > > >             3. LabelAndMessageRenderer do this for render a Label an a
> > > >             field (please look the parts in yellow)
> > > >
> > > >               private void _renderLabelCell(
> > > >                 FacesContext        context,
> > > >                 RenderingContext arc,
> > > >                 UIComponent         component,
> > > >                 FacesBean           bean,
> > > >                 boolean             labelExists) throws IOException
> > > >               {
> > > >                 ResponseWriter rw = context.getResponseWriter();
> > > >                 rw.startElement("td", null);
> > > >
> > > >                 // render labelStyleClass and defaultStyleClass.
> > > >                 renderStyleClasses(context, arc, new String[]{
> > > >
> getLabelStyleClass(bean),
> > > >
> _getDefaultLabelStyleClass(arc,
> > > >
> > > >             SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS
> )});
> > > >
> > > >                 String labelInlineStyle =
> getLabelInlineStyleKey(bean);
> > > >                 rw.writeAttribute("style", labelInlineStyle, null);
> > > >
> > > >                 String valign = getDefaultLabelValign(bean);
> > > >
> > > >                 rw.writeAttribute ("valign", valign, null);
> > > >                 if (isDesktop(arc))
> > > >                   rw.writeAttribute("nowrap", Boolean.TRUE, null);
> > > >
> > > >                 if (labelExists)
> > > >                 {
> > > >                   rw.writeAttribute("width",
> > > >
> > > >             arc.getProperties().get(_LABEL_CELL_WIDTH_KEY),
> > > >                                     null);
> > > >                 }
> > > >
> > > >                 delegateRenderer(context, arc, component, bean,
> _label);
> > > >                 rw.endElement ("td");
> > > >               }
> > > >
> > > >               private void _renderFieldCell(
> > > >                 FacesContext        context,
> > > >                 RenderingContext arc,
> > > >                 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);
> > > >                 rw.writeAttribute("nowrap", Boolean.TRUE, null);
> > > >
> > > >                 renderStyleClass(context, arc,
> > > >             SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS
> );
> > > >
> > > >                 if (labelExists)
> > > >                   rw.writeAttribute("width",
> > > >
> > > >             arc.getProperties().get(_FIELD_CELL_WIDTH_KEY),
> > > >                                     null);
> > > >
> > > >                 renderFieldCellContents(context, arc,
> 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, arc, component,
> > > >             bean))
> > > >                   {
> > > >                     rw.startElement ("div", null);
> > > >                     renderStyleClass(context, arc,
> > > >
> > > >
> SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS);
> > > >
> _renderMessageCellContents(context, arc,
> > > >             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(arc) && isIE(arc))
> > > >                 {
> > > >                   rw.startElement("div", null);
> > > >                   renderSpacer(context, arc, "1", "0");
> > > >                   rw.endElement("div");
> > > >                 }
> > > >
> > > >                 rw.endElement("td");
> > > >               }
> > > >
> > > >             I need to add an attribute in the td tag like <td
> > > >             colspan=2 rowspan=3 height=XXX width=XXX .........>, but
> > > >             if i want this, i need to
> > > >             modify LabelAndMessageRenderer to recognize if the parent
> > > >             component is my component, check if it has an attribute
> > > >             like this
> > > >
> > > >
> <mycomp:tableFormLayout
> > > >             labelWidth="100"  width="400" height="300"
> > > >                                     fieldWidth="100"
> rows="100"
> > > >             columns="1*;1*;1*" >
> > > >
> <tr:selectOneChoice
> > > >             label="Salutation">
> > > >                                         <f:selectItem
> itemLabel="1
> > > >             Option" itemValue="1" />
> > > >                                         <f:attribute
> name="spanXItem"
> > > >             value="2"/>
> > > >                                         <f:attribute
> name="spanYItem"
> > > >             value="3"/>
> > > >
> </tr:selectOneChoice>
> > > >
> </mycomp:tableFormLayout>
> > > >
> > > >             and finally add a colspan or rowspan (height and width are
> > > >             optional).
> > > >
> > > >             ---------
> > > >             Conclusion?: It's necesary to decouple
> > > >             PanelFormLayoutRenderer and other FormRenderers with
> > > >             LabelAndMessageRenderer in order to avoid
> > > >             those hacks. I propose to create an interface that
> > > >             implements some affected methods or create new ones, and
> > > >             delegate this rendering to the parent
> > > >             classes.
> > > >
> > > >             I want to you what should be better to do in that case. If
> > > >             its necesary to refactor the classes, how it can be done.
> > > >
> > > >             Thanks for your attention
> > > >
> > > >             regards
> > > >
> > > >             Att: Leonardo Uribe
> > > >             Ingeniero de Sistemas
> > > >             Pontificia Universidad Javeriana
> > > >             Ingeniero Electronico
> > > >             Universidad Nacional de Colombia
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > > >
> > >
> >
> >
>
>
>
> --
> Chordiant Software Inc.
> www.chordiant.com


-- 

http://www.irian.at

Your JSF powerhouse -
JSF Consulting, Development and
Courses in English and German

Professional Support for Apache MyFaces

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Danny Robinson <da...@gmail.com>.
+1 (non-binding)

On 6/6/07, Simon Lessard <si...@gmail.com> wrote:
>
> +1 here as well, we had that issue on a project just last week.
>
> On 6/6/07, Jeanne Waldman <jeanne.waldman@oracle.com > wrote:
> >
> > +1 also.
> >
> > Matt Cooper wrote:
> > > +1 on supporting an iterator around form items, I feel that would be
> > > quite a powerful enhancement
> > >
> > > On 6/5/07, *Adam Winer* < awiner@gmail.com <ma...@gmail.com>>
> > > wrote:
> > >
> > >     On 6/4/07, * Matt Cooper* <matt.faces@gmail.com
> > >     <ma...@gmail.com>> wrote:
> > >
> > >         I think decoupling of these renderers would be a good thing.
> > >         The trick will be to make sure the form item renders properly
> > >         when it is a direct child of the form layout component.  Let's
> >
> > >         say that you put a tr:panelGroupLayout (or some other non form
> > >         layout component) inbetween the form layout component and the
> > >         form item--I feel that that particular form item should render
> >
> > >         the same as if there was no form layout involved (this would
> > >         be insulating the form item from the form layout).
> > >
> > >
> > >     One of the big questions to decide when decoupling is whether you
> > >     want the parent component to augment/enhance the rendering of the
> > >     children or for the child to be passed more information to render
> > >     itself differently.  In this case, I wonder if both might be
> > >     desirable, and I could imagine:
> > >     - A generic mechanism whereby a parent renderer could say "on my
> > >     children, here's a CoreRendererDecorator that I'd like to have
> > >     called for any child CoreRenderer", akin to a servlet fil
> > >     - A generic mechanism whereby a parent could publish rendering
> > >     information and child could ask for it, decoupled from looking at
> > >     the renderer and component (so we don't have getParent() or
> > >     getParent().getRenderer() and "instanceof" calls), something like
> > >     Object RenderingContext.getDescriptor(UIComponent parent)?  This'd
> > >     let us have classes like FormLayoutData in the public API,
> > >     decoupling the renderers, without forcing us to move the renderers
> > >     themselves into the public API.
> > >
> > >
> > >         When considering a decoupling approach, you will also want
> > >         consider cases where a developer wants to have one kind of a
> > >         form layout component inside of another form layout
> > >         component.  There will need to be some sort of mechanism to
> > >         ensure the correct rendering path is taken for the each
> > >         particular component hierarchy so a simple "am I contained, at
> >
> > >         any level, in a form layout" might not be sufficient but an
> > >         "am I a direct child of a form layout" might.
> > >
> > >         Today, I believe if you have a tr:panelFormLayout inside of
> > >         another tr:panelFormLayout, the outer layout will have labels
> > >         on the side of the contents and the inner layout will have the
> > >         labels above the contents.  This is determined by a request
> > >         attribute that is present only during the encodeAll of the
> > >         PanelFormLayout's encoding.
> > >
> > >         One final tip...  There is one particular case where a form
> > >         item isn't a direct child of the form layout but will still
> > >         render as a form item:  when it is contained in a tr:group
> > >         component and that tr:group is a direct child of the form
> > >         layout.  The tr:group component is used by the form layout
> > >         renderer to draw separator lines between groups of form items.
> > >
> > >
> > >     And, in addition, I think a lot of people really wish that if you
> > >     had a tr:iterator inside of
> > >     a tr:panelFormLayout, that children of that iterator would render
> > >     as a form item.  I think
> > >     a CoreRendererDecorator approach might accomplish that...
> > >
> > >     -- Adam
> > >
> > >
> > >
> > >         Regards,
> > >         Matt
> > >
> > >
> > >         On 5/24/07, *Leonardo Uribe* <lu4242@gmail.com
> > >         <ma...@gmail.com>> wrote:
> > >
> > >             Hi everybody.
> > >
> > >             I'm working on a trinidad component for do layout (as part
> > >             of a Google Summer of Code) more easy and with less code
> > >             than panelFormLayout component.
> > >
> > >             Checking the code, I found a strong coupling between the
> > >             classes PanelFormLayoutRenderer and
> > LabelAndMessageRenderer.
> > >
> > >             I found the following points:
> > >
> > >             1. LabelAndMessageRenderer has about 3 behaviors,
> > >             depending what is his parent components. In the code it
> > >             checks in a method something like
> > >             that:
> > >
> > >               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) ;
> > >               }
> > >
> > >             Because my component is a new component, i have to add a
> > >             line like this
> > >
> > >                 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);
> > >
> > >             But this is very hacky. I have to do this because i need
> > >             that the method in encodeAll of LabelAndMessageRenderer
> > >
> > >             boolean needsPanelFormLayout =
> > _isParentPanelForm(component);
> > >
> > >             returns true, because my component layout a table like
> > >             panelFormLayout.
> > >
> > >             2. In other part of the code, LabelAndMessageRenderer call
> > >             this method (in encodeAll)
> > >
> > >                   if (needsPanelFormLayout)
> > >                   {
> > >
> > >             if(PanelFormLayoutRenderer.encodeBetweenLabelAndFieldCells
> > (context,
> > >             arc, rw))
> > >                     {
> > >                       renderRootDomElementStyles(context, arc,
> > >             component, bean);
> > >                     }
> > >                   }
> > >
> > >             What if my component has another behavior to this method?
> > >             PanelFormLayoutRenderer detects if this panelFormLayout is
> >
> > >             inside
> > >             another panelFormLayout and because if it is the case, it
> > >             adds between Label and Field Cells something like this
> > >
> > >                   rw.endElement ("tr"); // label row
> > >                   rw.startElement("tr", null); // field row
> > >
> > >             So, the label is rendered on top of the field.
> > >
> > >             3. LabelAndMessageRenderer do this for render a Label an a
> >
> > >             field (please look the parts in yellow)
> > >
> > >               private void _renderLabelCell(
> > >                 FacesContext        context,
> > >                 RenderingContext arc,
> > >                 UIComponent         component,
> > >                 FacesBean           bean,
> > >                 boolean             labelExists) throws IOException
> > >               {
> > >                 ResponseWriter rw = context.getResponseWriter();
> > >                 rw.startElement("td", null);
> > >
> > >                 // render labelStyleClass and defaultStyleClass.
> > >                 renderStyleClasses(context, arc, new String[]{
> > >                                    getLabelStyleClass(bean),
> > >                                    _getDefaultLabelStyleClass(arc,
> > >
> > >             SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS )});
> > >
> > >                 String labelInlineStyle =
> > getLabelInlineStyleKey(bean);
> > >                 rw.writeAttribute("style", labelInlineStyle, null);
> > >
> > >                 String valign = getDefaultLabelValign(bean);
> > >
> > >                 rw.writeAttribute ("valign", valign, null);
> > >                 if (isDesktop(arc))
> > >                   rw.writeAttribute("nowrap", Boolean.TRUE, null);
> > >
> > >                 if (labelExists)
> > >                 {
> > >                   rw.writeAttribute("width",
> > >
> > >             arc.getProperties().get(_LABEL_CELL_WIDTH_KEY),
> > >                                     null);
> > >                 }
> > >
> > >                 delegateRenderer(context, arc, component, bean,
> > _label);
> > >                 rw.endElement ("td");
> > >               }
> > >
> > >               private void _renderFieldCell(
> > >                 FacesContext        context,
> > >                 RenderingContext arc,
> > >                 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);
> > >                 rw.writeAttribute("nowrap", Boolean.TRUE, null);
> > >
> > >                 renderStyleClass(context, arc,
> > >             SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS );
> > >
> > >                 if (labelExists)
> > >                   rw.writeAttribute("width",
> > >
> > >             arc.getProperties().get(_FIELD_CELL_WIDTH_KEY),
> > >                                     null);
> > >
> > >                 renderFieldCellContents(context, arc, 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, arc, component,
> > >             bean))
> > >                   {
> > >                     rw.startElement ("div", null);
> > >                     renderStyleClass(context, arc,
> > >
> > >             SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS);
> > >                     _renderMessageCellContents(context, arc,
> > >             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(arc) && isIE(arc))
> > >                 {
> > >                   rw.startElement("div", null);
> > >                   renderSpacer(context, arc, "1", "0");
> > >                   rw.endElement("div");
> > >                 }
> > >
> > >                 rw.endElement("td");
> > >               }
> > >
> > >             I need to add an attribute in the td tag like <td
> > >             colspan=2 rowspan=3 height=XXX width=XXX .........>, but
> > >             if i want this, i need to
> > >             modify LabelAndMessageRenderer to recognize if the parent
> > >             component is my component, check if it has an attribute
> > >             like this
> > >
> > >                                 <mycomp:tableFormLayout
> > >             labelWidth="100"  width="400" height="300"
> > >                                     fieldWidth="100" rows="100"
> > >             columns="1*;1*;1*" >
> > >                                     <tr:selectOneChoice
> > >             label="Salutation">
> > >                                         <f:selectItem itemLabel="1
> > >             Option" itemValue="1" />
> > >                                         <f:attribute name="spanXItem"
> > >             value="2"/>
> > >                                         <f:attribute name="spanYItem"
> > >             value="3"/>
> > >                                     </tr:selectOneChoice>
> > >                                 </mycomp:tableFormLayout>
> > >
> > >             and finally add a colspan or rowspan (height and width are
> >
> > >             optional).
> > >
> > >             ---------
> > >             Conclusion?: It's necesary to decouple
> > >             PanelFormLayoutRenderer and other FormRenderers with
> > >             LabelAndMessageRenderer in order to avoid
> > >             those hacks. I propose to create an interface that
> > >             implements some affected methods or create new ones, and
> > >             delegate this rendering to the parent
> > >             classes.
> > >
> > >             I want to you what should be better to do in that case. If
> > >             its necesary to refactor the classes, how it can be done.
> > >
> > >             Thanks for your attention
> > >
> > >             regards
> > >
> > >             Att: Leonardo Uribe
> > >             Ingeniero de Sistemas
> > >             Pontificia Universidad Javeriana
> > >             Ingeniero Electronico
> > >             Universidad Nacional de Colombia
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> >
>
>


-- 
Chordiant Software Inc.
www.chordiant.com

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Simon Lessard <si...@gmail.com>.
+1 here as well, we had that issue on a project just last week.

On 6/6/07, Jeanne Waldman <je...@oracle.com> wrote:
>
> +1 also.
>
> Matt Cooper wrote:
> > +1 on supporting an iterator around form items, I feel that would be
> > quite a powerful enhancement
> >
> > On 6/5/07, *Adam Winer* < awiner@gmail.com <ma...@gmail.com>>
> > wrote:
> >
> >     On 6/4/07, * Matt Cooper* <matt.faces@gmail.com
> >     <ma...@gmail.com>> wrote:
> >
> >         I think decoupling of these renderers would be a good thing.
> >         The trick will be to make sure the form item renders properly
> >         when it is a direct child of the form layout component.  Let's
> >         say that you put a tr:panelGroupLayout (or some other non form
> >         layout component) inbetween the form layout component and the
> >         form item--I feel that that particular form item should render
> >         the same as if there was no form layout involved (this would
> >         be insulating the form item from the form layout).
> >
> >
> >     One of the big questions to decide when decoupling is whether you
> >     want the parent component to augment/enhance the rendering of the
> >     children or for the child to be passed more information to render
> >     itself differently.  In this case, I wonder if both might be
> >     desirable, and I could imagine:
> >     - A generic mechanism whereby a parent renderer could say "on my
> >     children, here's a CoreRendererDecorator that I'd like to have
> >     called for any child CoreRenderer", akin to a servlet fil
> >     - A generic mechanism whereby a parent could publish rendering
> >     information and child could ask for it, decoupled from looking at
> >     the renderer and component (so we don't have getParent() or
> >     getParent().getRenderer() and "instanceof" calls), something like
> >     Object RenderingContext.getDescriptor(UIComponent parent)?  This'd
> >     let us have classes like FormLayoutData in the public API,
> >     decoupling the renderers, without forcing us to move the renderers
> >     themselves into the public API.
> >
> >
> >         When considering a decoupling approach, you will also want
> >         consider cases where a developer wants to have one kind of a
> >         form layout component inside of another form layout
> >         component.  There will need to be some sort of mechanism to
> >         ensure the correct rendering path is taken for the each
> >         particular component hierarchy so a simple "am I contained, at
> >         any level, in a form layout" might not be sufficient but an
> >         "am I a direct child of a form layout" might.
> >
> >         Today, I believe if you have a tr:panelFormLayout inside of
> >         another tr:panelFormLayout, the outer layout will have labels
> >         on the side of the contents and the inner layout will have the
> >         labels above the contents.  This is determined by a request
> >         attribute that is present only during the encodeAll of the
> >         PanelFormLayout's encoding.
> >
> >         One final tip...  There is one particular case where a form
> >         item isn't a direct child of the form layout but will still
> >         render as a form item:  when it is contained in a tr:group
> >         component and that tr:group is a direct child of the form
> >         layout.  The tr:group component is used by the form layout
> >         renderer to draw separator lines between groups of form items.
> >
> >
> >     And, in addition, I think a lot of people really wish that if you
> >     had a tr:iterator inside of
> >     a tr:panelFormLayout, that children of that iterator would render
> >     as a form item.  I think
> >     a CoreRendererDecorator approach might accomplish that...
> >
> >     -- Adam
> >
> >
> >
> >         Regards,
> >         Matt
> >
> >
> >         On 5/24/07, *Leonardo Uribe* <lu4242@gmail.com
> >         <ma...@gmail.com>> wrote:
> >
> >             Hi everybody.
> >
> >             I'm working on a trinidad component for do layout (as part
> >             of a Google Summer of Code) more easy and with less code
> >             than panelFormLayout component.
> >
> >             Checking the code, I found a strong coupling between the
> >             classes PanelFormLayoutRenderer and LabelAndMessageRenderer.
> >
> >             I found the following points:
> >
> >             1. LabelAndMessageRenderer has about 3 behaviors,
> >             depending what is his parent components. In the code it
> >             checks in a method something like
> >             that:
> >
> >               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) ;
> >               }
> >
> >             Because my component is a new component, i have to add a
> >             line like this
> >
> >                 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);
> >
> >             But this is very hacky. I have to do this because i need
> >             that the method in encodeAll of LabelAndMessageRenderer
> >
> >             boolean needsPanelFormLayout =
> _isParentPanelForm(component);
> >
> >             returns true, because my component layout a table like
> >             panelFormLayout.
> >
> >             2. In other part of the code, LabelAndMessageRenderer call
> >             this method (in encodeAll)
> >
> >                   if (needsPanelFormLayout)
> >                   {
> >
> >             if(PanelFormLayoutRenderer.encodeBetweenLabelAndFieldCells
> (context,
> >             arc, rw))
> >                     {
> >                       renderRootDomElementStyles(context, arc,
> >             component, bean);
> >                     }
> >                   }
> >
> >             What if my component has another behavior to this method?
> >             PanelFormLayoutRenderer detects if this panelFormLayout is
> >             inside
> >             another panelFormLayout and because if it is the case, it
> >             adds between Label and Field Cells something like this
> >
> >                   rw.endElement("tr"); // label row
> >                   rw.startElement("tr", null); // field row
> >
> >             So, the label is rendered on top of the field.
> >
> >             3. LabelAndMessageRenderer do this for render a Label an a
> >             field (please look the parts in yellow)
> >
> >               private void _renderLabelCell(
> >                 FacesContext        context,
> >                 RenderingContext arc,
> >                 UIComponent         component,
> >                 FacesBean           bean,
> >                 boolean             labelExists) throws IOException
> >               {
> >                 ResponseWriter rw = context.getResponseWriter();
> >                 rw.startElement("td", null);
> >
> >                 // render labelStyleClass and defaultStyleClass.
> >                 renderStyleClasses(context, arc, new String[]{
> >                                    getLabelStyleClass(bean),
> >                                    _getDefaultLabelStyleClass(arc,
> >
> >             SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS )});
> >
> >                 String labelInlineStyle = getLabelInlineStyleKey(bean);
> >                 rw.writeAttribute("style", labelInlineStyle, null);
> >
> >                 String valign = getDefaultLabelValign(bean);
> >
> >                 rw.writeAttribute ("valign", valign, null);
> >                 if (isDesktop(arc))
> >                   rw.writeAttribute("nowrap", Boolean.TRUE, null);
> >
> >                 if (labelExists)
> >                 {
> >                   rw.writeAttribute("width",
> >
> >             arc.getProperties().get(_LABEL_CELL_WIDTH_KEY),
> >                                     null);
> >                 }
> >
> >                 delegateRenderer(context, arc, component, bean, _label);
> >                 rw.endElement ("td");
> >               }
> >
> >               private void _renderFieldCell(
> >                 FacesContext        context,
> >                 RenderingContext arc,
> >                 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);
> >                 rw.writeAttribute("nowrap", Boolean.TRUE, null);
> >
> >                 renderStyleClass(context, arc,
> >             SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS );
> >
> >                 if (labelExists)
> >                   rw.writeAttribute("width",
> >
> >             arc.getProperties().get(_FIELD_CELL_WIDTH_KEY),
> >                                     null);
> >
> >                 renderFieldCellContents(context, arc, 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, arc, component,
> >             bean))
> >                   {
> >                     rw.startElement("div", null);
> >                     renderStyleClass(context, arc,
> >
> >             SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS);
> >                     _renderMessageCellContents(context, arc,
> >             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(arc) && isIE(arc))
> >                 {
> >                   rw.startElement("div", null);
> >                   renderSpacer(context, arc, "1", "0");
> >                   rw.endElement("div");
> >                 }
> >
> >                 rw.endElement("td");
> >               }
> >
> >             I need to add an attribute in the td tag like <td
> >             colspan=2 rowspan=3 height=XXX width=XXX .........>, but
> >             if i want this, i need to
> >             modify LabelAndMessageRenderer to recognize if the parent
> >             component is my component, check if it has an attribute
> >             like this
> >
> >                                 <mycomp:tableFormLayout
> >             labelWidth="100"  width="400" height="300"
> >                                     fieldWidth="100" rows="100"
> >             columns="1*;1*;1*" >
> >                                     <tr:selectOneChoice
> >             label="Salutation">
> >                                         <f:selectItem itemLabel="1
> >             Option" itemValue="1" />
> >                                         <f:attribute name="spanXItem"
> >             value="2"/>
> >                                         <f:attribute name="spanYItem"
> >             value="3"/>
> >                                     </tr:selectOneChoice>
> >                                 </mycomp:tableFormLayout>
> >
> >             and finally add a colspan or rowspan (height and width are
> >             optional).
> >
> >             ---------
> >             Conclusion?: It's necesary to decouple
> >             PanelFormLayoutRenderer and other FormRenderers with
> >             LabelAndMessageRenderer in order to avoid
> >             those hacks. I propose to create an interface that
> >             implements some affected methods or create new ones, and
> >             delegate this rendering to the parent
> >             classes.
> >
> >             I want to you what should be better to do in that case. If
> >             its necesary to refactor the classes, how it can be done.
> >
> >             Thanks for your attention
> >
> >             regards
> >
> >             Att: Leonardo Uribe
> >             Ingeniero de Sistemas
> >             Pontificia Universidad Javeriana
> >             Ingeniero Electronico
> >             Universidad Nacional de Colombia
> >
> >
> >
> >
> >
> >
> >
> >
> >
> >
>

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Jeanne Waldman <je...@oracle.com>.
+1 also.

Matt Cooper wrote:
> +1 on supporting an iterator around form items, I feel that would be 
> quite a powerful enhancement
>
> On 6/5/07, *Adam Winer* < awiner@gmail.com <ma...@gmail.com>> 
> wrote:
>
>     On 6/4/07, * Matt Cooper* <matt.faces@gmail.com
>     <ma...@gmail.com>> wrote:
>
>         I think decoupling of these renderers would be a good thing. 
>         The trick will be to make sure the form item renders properly
>         when it is a direct child of the form layout component.  Let's
>         say that you put a tr:panelGroupLayout (or some other non form
>         layout component) inbetween the form layout component and the
>         form item--I feel that that particular form item should render
>         the same as if there was no form layout involved (this would
>         be insulating the form item from the form layout). 
>
>
>     One of the big questions to decide when decoupling is whether you
>     want the parent component to augment/enhance the rendering of the
>     children or for the child to be passed more information to render
>     itself differently.  In this case, I wonder if both might be
>     desirable, and I could imagine:
>     - A generic mechanism whereby a parent renderer could say "on my
>     children, here's a CoreRendererDecorator that I'd like to have
>     called for any child CoreRenderer", akin to a servlet fil
>     - A generic mechanism whereby a parent could publish rendering
>     information and child could ask for it, decoupled from looking at
>     the renderer and component (so we don't have getParent() or
>     getParent().getRenderer() and "instanceof" calls), something like
>     Object RenderingContext.getDescriptor(UIComponent parent)?  This'd
>     let us have classes like FormLayoutData in the public API,
>     decoupling the renderers, without forcing us to move the renderers
>     themselves into the public API.
>      
>
>         When considering a decoupling approach, you will also want
>         consider cases where a developer wants to have one kind of a
>         form layout component inside of another form layout
>         component.  There will need to be some sort of mechanism to
>         ensure the correct rendering path is taken for the each
>         particular component hierarchy so a simple "am I contained, at
>         any level, in a form layout" might not be sufficient but an
>         "am I a direct child of a form layout" might.
>
>         Today, I believe if you have a tr:panelFormLayout inside of
>         another tr:panelFormLayout, the outer layout will have labels
>         on the side of the contents and the inner layout will have the
>         labels above the contents.  This is determined by a request
>         attribute that is present only during the encodeAll of the
>         PanelFormLayout's encoding.
>
>         One final tip...  There is one particular case where a form
>         item isn't a direct child of the form layout but will still
>         render as a form item:  when it is contained in a tr:group
>         component and that tr:group is a direct child of the form
>         layout.  The tr:group component is used by the form layout
>         renderer to draw separator lines between groups of form items. 
>
>
>     And, in addition, I think a lot of people really wish that if you
>     had a tr:iterator inside of
>     a tr:panelFormLayout, that children of that iterator would render
>     as a form item.  I think
>     a CoreRendererDecorator approach might accomplish that...
>
>     -- Adam
>
>      
>
>         Regards,
>         Matt
>
>
>         On 5/24/07, *Leonardo Uribe* <lu4242@gmail.com
>         <ma...@gmail.com>> wrote:
>
>             Hi everybody.
>
>             I'm working on a trinidad component for do layout (as part
>             of a Google Summer of Code) more easy and with less code
>             than panelFormLayout component.
>
>             Checking the code, I found a strong coupling between the
>             classes PanelFormLayoutRenderer and LabelAndMessageRenderer.
>
>             I found the following points:
>
>             1. LabelAndMessageRenderer has about 3 behaviors,
>             depending what is his parent components. In the code it
>             checks in a method something like
>             that:
>
>               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) ;
>               }
>
>             Because my component is a new component, i have to add a
>             line like this
>
>                 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);
>
>             But this is very hacky. I have to do this because i need
>             that the method in encodeAll of LabelAndMessageRenderer
>
>             boolean needsPanelFormLayout = _isParentPanelForm(component);
>
>             returns true, because my component layout a table like
>             panelFormLayout.
>
>             2. In other part of the code, LabelAndMessageRenderer call
>             this method (in encodeAll)
>
>                   if (needsPanelFormLayout)
>                   {
>                    
>             if(PanelFormLayoutRenderer.encodeBetweenLabelAndFieldCells(context,
>             arc, rw))
>                     {
>                       renderRootDomElementStyles(context, arc,
>             component, bean);
>                     }
>                   }
>
>             What if my component has another behavior to this method?
>             PanelFormLayoutRenderer detects if this panelFormLayout is
>             inside
>             another panelFormLayout and because if it is the case, it
>             adds between Label and Field Cells something like this
>
>                   rw.endElement("tr"); // label row
>                   rw.startElement("tr", null); // field row
>
>             So, the label is rendered on top of the field.
>
>             3. LabelAndMessageRenderer do this for render a Label an a
>             field (please look the parts in yellow)
>
>               private void _renderLabelCell(
>                 FacesContext        context,
>                 RenderingContext arc,
>                 UIComponent         component,
>                 FacesBean           bean,
>                 boolean             labelExists) throws IOException
>               {
>                 ResponseWriter rw = context.getResponseWriter();
>                 rw.startElement("td", null);
>                
>                 // render labelStyleClass and defaultStyleClass.
>                 renderStyleClasses(context, arc, new String[]{
>                                    getLabelStyleClass(bean),
>                                    _getDefaultLabelStyleClass(arc,
>                                      
>             SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS )});
>
>                 String labelInlineStyle = getLabelInlineStyleKey(bean);
>                 rw.writeAttribute("style", labelInlineStyle, null);
>
>                 String valign = getDefaultLabelValign(bean);
>
>                 rw.writeAttribute ("valign", valign, null);
>                 if (isDesktop(arc))
>                   rw.writeAttribute("nowrap", Boolean.TRUE, null);
>
>                 if (labelExists)
>                 {
>                   rw.writeAttribute("width",
>                                    
>             arc.getProperties().get(_LABEL_CELL_WIDTH_KEY),
>                                     null);
>                 }
>
>                 delegateRenderer(context, arc, component, bean, _label);
>                 rw.endElement ("td");
>               }
>
>               private void _renderFieldCell(
>                 FacesContext        context,
>                 RenderingContext arc,
>                 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);
>                 rw.writeAttribute("nowrap", Boolean.TRUE, null);
>
>                 renderStyleClass(context, arc,
>             SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS );
>
>                 if (labelExists)
>                   rw.writeAttribute("width",
>                                    
>             arc.getProperties().get(_FIELD_CELL_WIDTH_KEY),
>                                     null);
>
>                 renderFieldCellContents(context, arc, 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, arc, component,
>             bean))
>                   {
>                     rw.startElement("div", null);
>                     renderStyleClass(context, arc,
>                                     
>             SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS);
>                     _renderMessageCellContents(context, arc,
>             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(arc) && isIE(arc))
>                 {
>                   rw.startElement("div", null);
>                   renderSpacer(context, arc, "1", "0");
>                   rw.endElement("div");
>                 }
>
>                 rw.endElement("td");
>               }
>
>             I need to add an attribute in the td tag like <td
>             colspan=2 rowspan=3 height=XXX width=XXX .........>, but
>             if i want this, i need to
>             modify LabelAndMessageRenderer to recognize if the parent
>             component is my component, check if it has an attribute
>             like this
>
>                                 <mycomp:tableFormLayout
>             labelWidth="100"  width="400" height="300"
>                                     fieldWidth="100" rows="100"
>             columns="1*;1*;1*" >
>                                     <tr:selectOneChoice
>             label="Salutation">
>                                         <f:selectItem itemLabel="1
>             Option" itemValue="1" />
>                                         <f:attribute name="spanXItem"
>             value="2"/>
>                                         <f:attribute name="spanYItem"
>             value="3"/>
>                                     </tr:selectOneChoice>
>                                 </mycomp:tableFormLayout>
>
>             and finally add a colspan or rowspan (height and width are
>             optional).
>
>             ---------
>             Conclusion?: It's necesary to decouple
>             PanelFormLayoutRenderer and other FormRenderers with
>             LabelAndMessageRenderer in order to avoid
>             those hacks. I propose to create an interface that
>             implements some affected methods or create new ones, and
>             delegate this rendering to the parent
>             classes.
>
>             I want to you what should be better to do in that case. If
>             its necesary to refactor the classes, how it can be done.
>
>             Thanks for your attention
>
>             regards
>
>             Att: Leonardo Uribe
>             Ingeniero de Sistemas
>             Pontificia Universidad Javeriana
>             Ingeniero Electronico
>             Universidad Nacional de Colombia
>
>
>
>
>
>
>
>
>
>

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Matt Cooper <ma...@gmail.com>.
+1 on supporting an iterator around form items, I feel that would be quite a
powerful enhancement

On 6/5/07, Adam Winer <aw...@gmail.com> wrote:
>
> On 6/4/07, Matt Cooper <ma...@gmail.com> wrote:
> >
> > I think decoupling of these renderers would be a good thing.  The trick
> > will be to make sure the form item renders properly when it is a direct
> > child of the form layout component.  Let's say that you put a
> > tr:panelGroupLayout (or some other non form layout component) inbetween the
> > form layout component and the form item--I feel that that particular form
> > item should render the same as if there was no form layout involved (this
> > would be insulating the form item from the form layout).
>
>
> One of the big questions to decide when decoupling is whether you want the
> parent component to augment/enhance the rendering of the children or for the
> child to be passed more information to render itself differently.  In this
> case, I wonder if both might be desirable, and I could imagine:
> - A generic mechanism whereby a parent renderer could say "on my children,
> here's a CoreRendererDecorator that I'd like to have called for any child
> CoreRenderer", akin to a servlet fil
> - A generic mechanism whereby a parent could publish rendering information
> and child could ask for it, decoupled from looking at the renderer and
> component (so we don't have getParent() or getParent().getRenderer() and
> "instanceof" calls), something like Object RenderingContext.getDescriptor(UIComponent
> parent)?  This'd let us have classes like FormLayoutData in the public API,
> decoupling the renderers, without forcing us to move the renderers
> themselves into the public API.
>
>
> When considering a decoupling approach, you will also want consider cases
> > where a developer wants to have one kind of a form layout component inside
> > of another form layout component.  There will need to be some sort of
> > mechanism to ensure the correct rendering path is taken for the each
> > particular component hierarchy so a simple "am I contained, at any level, in
> > a form layout" might not be sufficient but an "am I a direct child of a form
> > layout" might.
> >
> > Today, I believe if you have a tr:panelFormLayout inside of another
> > tr:panelFormLayout, the outer layout will have labels on the side of the
> > contents and the inner layout will have the labels above the contents.  This
> > is determined by a request attribute that is present only during the
> > encodeAll of the PanelFormLayout's encoding.
> >
> > One final tip...  There is one particular case where a form item isn't a
> > direct child of the form layout but will still render as a form item:  when
> > it is contained in a tr:group component and that tr:group is a direct child
> > of the form layout.  The tr:group component is used by the form layout
> > renderer to draw separator lines between groups of form items.
>
>
> And, in addition, I think a lot of people really wish that if you had a
> tr:iterator inside of
> a tr:panelFormLayout, that children of that iterator would render as a
> form item.  I think
> a CoreRendererDecorator approach might accomplish that...
>
> -- Adam
>
>
>
> Regards,
> > Matt
> >
> > On 5/24/07, Leonardo Uribe <lu4242@gmail.com > wrote:
> > >
> > > Hi everybody.
> > >
> > > I'm working on a trinidad component for do layout (as part of a Google
> > > Summer of Code) more easy and with less code than panelFormLayout
> > > component.
> > >
> > > Checking the code, I found a strong coupling between the classes
> > > PanelFormLayoutRenderer and LabelAndMessageRenderer.
> > >
> > > I found the following points:
> > >
> > > 1. LabelAndMessageRenderer has about 3 behaviors, depending what is
> > > his parent components. In the code it checks in a method something
> > > like
> > > that:
> > >
> > >   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)
> > > ;
> > >   }
> > >
> > > Because my component is a new component, i have to add a line like
> > > this
> > >
> > >     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);
> > >
> > > But this is very hacky. I have to do this because i need that the
> > > method in encodeAll of LabelAndMessageRenderer
> > >
> > > boolean needsPanelFormLayout = _isParentPanelForm(component);
> > >
> > > returns true, because my component layout a table like
> > > panelFormLayout.
> > >
> > > 2. In other part of the code, LabelAndMessageRenderer call this method
> > > (in encodeAll)
> > >
> > >       if (needsPanelFormLayout)
> > >       {
> > >         if(PanelFormLayoutRenderer.encodeBetweenLabelAndFieldCells(context,
> > > arc, rw))
> > >         {
> > >           renderRootDomElementStyles(context, arc, component, bean);
> > >         }
> > >       }
> > >
> > > What if my component has another behavior to this method?
> > > PanelFormLayoutRenderer detects if this panelFormLayout is inside
> > > another panelFormLayout and because if it is the case, it adds between
> > > Label and Field Cells something like this
> > >
> > >       rw.endElement("tr"); // label row
> > >       rw.startElement("tr", null); // field row
> > >
> > > So, the label is rendered on top of the field.
> > >
> > > 3. LabelAndMessageRenderer do this for render a Label an a field
> > > (please look the parts in yellow)
> > >
> > >   private void _renderLabelCell(
> > >     FacesContext        context,
> > >     RenderingContext arc,
> > >     UIComponent         component,
> > >     FacesBean           bean,
> > >     boolean             labelExists) throws IOException
> > >   {
> > >     ResponseWriter rw = context.getResponseWriter();
> > >     rw.startElement("td", null);
> > >
> > >     // render labelStyleClass and defaultStyleClass.
> > >     renderStyleClasses(context, arc, new String[]{
> > >                        getLabelStyleClass(bean),
> > >                        _getDefaultLabelStyleClass(arc,
> > >                           SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS )});
> > >
> > >     String labelInlineStyle = getLabelInlineStyleKey(bean);
> > >     rw.writeAttribute("style", labelInlineStyle, null);
> > >
> > >     String valign = getDefaultLabelValign(bean);
> > >
> > >     rw.writeAttribute ("valign", valign, null);
> > >     if (isDesktop(arc))
> > >       rw.writeAttribute("nowrap", Boolean.TRUE, null);
> > >
> > >     if (labelExists)
> > >     {
> > >       rw.writeAttribute("width",
> > >                         arc.getProperties
> > > ().get(_LABEL_CELL_WIDTH_KEY),
> > >                         null);
> > >     }
> > >
> > >     delegateRenderer(context, arc, component, bean, _label);
> > >     rw.endElement ("td");
> > >   }
> > >
> > >   private void _renderFieldCell(
> > >     FacesContext        context,
> > >     RenderingContext arc,
> > >     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);
> > >     rw.writeAttribute("nowrap", Boolean.TRUE, null);
> > >
> > >     renderStyleClass(context, arc,
> > > SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS );
> > >
> > >     if (labelExists)
> > >       rw.writeAttribute("width",
> > >                         arc.getProperties
> > > ().get(_FIELD_CELL_WIDTH_KEY),
> > >                         null);
> > >
> > >     renderFieldCellContents(context, arc, 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, arc, component, bean))
> > >       {
> > >         rw.startElement("div", null);
> > >         renderStyleClass(context, arc,
> > >
> > > SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS);
> > >         _renderMessageCellContents(context, arc, 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(arc) && isIE(arc))
> > >     {
> > >       rw.startElement("div", null);
> > >       renderSpacer(context, arc, "1", "0");
> > >       rw.endElement("div");
> > >     }
> > >
> > >     rw.endElement("td");
> > >   }
> > >
> > > I need to add an attribute in the td tag like <td colspan=2 rowspan=3
> > > height=XXX width=XXX .........>, but if i want this, i need to
> > > modify LabelAndMessageRenderer to recognize if the parent component is
> > > my component, check if it has an attribute like this
> > >
> > >                     <mycomp:tableFormLayout labelWidth="100"
> > > width="400" height="300"
> > >                         fieldWidth="100" rows="100" columns="1*;1*;1*"
> > > >
> > >                         <tr:selectOneChoice label="Salutation">
> > >                             <f:selectItem itemLabel="1 Option"
> > > itemValue="1" />
> > >                             <f:attribute name="spanXItem" value="2"/>
> > >                             <f:attribute name="spanYItem" value="3"/>
> > >                         </tr:selectOneChoice>
> > >                     </mycomp:tableFormLayout>
> > >
> > > and finally add a colspan or rowspan (height and width are optional).
> > >
> > > ---------
> > > Conclusion?: It's necesary to decouple PanelFormLayoutRenderer and
> > > other FormRenderers with LabelAndMessageRenderer in order to avoid
> > > those hacks. I propose to create an interface that implements some
> > > affected methods or create new ones, and delegate this rendering to the
> > > parent
> > > classes.
> > >
> > > I want to you what should be better to do in that case. If its
> > > necesary to refactor the classes, how it can be done.
> > >
> > > Thanks for your attention
> > >
> > > regards
> > >
> > > Att: Leonardo Uribe
> > > Ingeniero de Sistemas
> > > Pontificia Universidad Javeriana
> > > Ingeniero Electronico
> > > Universidad Nacional de Colombia
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> > >
> >
>

Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)

Posted by Adam Winer <aw...@gmail.com>.
On 6/4/07, Matt Cooper <ma...@gmail.com> wrote:
>
> I think decoupling of these renderers would be a good thing.  The trick
> will be to make sure the form item renders properly when it is a direct
> child of the form layout component.  Let's say that you put a
> tr:panelGroupLayout (or some other non form layout component) inbetween the
> form layout component and the form item--I feel that that particular form
> item should render the same as if there was no form layout involved (this
> would be insulating the form item from the form layout).


One of the big questions to decide when decoupling is whether you want the
parent component to augment/enhance the rendering of the children or for the
child to be passed more information to render itself differently.  In this
case, I wonder if both might be desirable, and I could imagine:
- A generic mechanism whereby a parent renderer could say "on my children,
here's a CoreRendererDecorator that I'd like to have called for any child
CoreRenderer", akin to a servlet fil
- A generic mechanism whereby a parent could publish rendering information
and child could ask for it, decoupled from looking at the renderer and
component (so we don't have getParent() or getParent().getRenderer() and
"instanceof" calls), something like Object
RenderingContext.getDescriptor(UIComponent
parent)?  This'd let us have classes like FormLayoutData in the public API,
decoupling the renderers, without forcing us to move the renderers
themselves into the public API.


When considering a decoupling approach, you will also want consider cases
> where a developer wants to have one kind of a form layout component inside
> of another form layout component.  There will need to be some sort of
> mechanism to ensure the correct rendering path is taken for the each
> particular component hierarchy so a simple "am I contained, at any level, in
> a form layout" might not be sufficient but an "am I a direct child of a form
> layout" might.
>
> Today, I believe if you have a tr:panelFormLayout inside of another
> tr:panelFormLayout, the outer layout will have labels on the side of the
> contents and the inner layout will have the labels above the contents.  This
> is determined by a request attribute that is present only during the
> encodeAll of the PanelFormLayout's encoding.
>
> One final tip...  There is one particular case where a form item isn't a
> direct child of the form layout but will still render as a form item:  when
> it is contained in a tr:group component and that tr:group is a direct child
> of the form layout.  The tr:group component is used by the form layout
> renderer to draw separator lines between groups of form items.


And, in addition, I think a lot of people really wish that if you had a
tr:iterator inside of
a tr:panelFormLayout, that children of that iterator would render as a form
item.  I think
a CoreRendererDecorator approach might accomplish that...

-- Adam



Regards,
> Matt
>
> On 5/24/07, Leonardo Uribe <lu...@gmail.com> wrote:
> >
> > Hi everybody.
> >
> > I'm working on a trinidad component for do layout (as part of a Google
> > Summer of Code) more easy and with less code than panelFormLayout
> > component.
> >
> > Checking the code, I found a strong coupling between the classes
> > PanelFormLayoutRenderer and LabelAndMessageRenderer.
> >
> > I found the following points:
> >
> > 1. LabelAndMessageRenderer has about 3 behaviors, depending what is his
> > parent components. In the code it checks in a method something like
> > that:
> >
> >   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) ;
> >   }
> >
> > Because my component is a new component, i have to add a line like this
> >
> >     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);
> >
> > But this is very hacky. I have to do this because i need that the method
> > in encodeAll of LabelAndMessageRenderer
> >
> > boolean needsPanelFormLayout = _isParentPanelForm(component);
> >
> > returns true, because my component layout a table like panelFormLayout.
> >
> > 2. In other part of the code, LabelAndMessageRenderer call this method
> > (in encodeAll)
> >
> >       if (needsPanelFormLayout)
> >       {
> >         if(PanelFormLayoutRenderer.encodeBetweenLabelAndFieldCells(context,
> > arc, rw))
> >         {
> >           renderRootDomElementStyles(context, arc, component, bean);
> >         }
> >       }
> >
> > What if my component has another behavior to this method?
> > PanelFormLayoutRenderer detects if this panelFormLayout is inside
> > another panelFormLayout and because if it is the case, it adds between
> > Label and Field Cells something like this
> >
> >       rw.endElement("tr"); // label row
> >       rw.startElement("tr", null); // field row
> >
> > So, the label is rendered on top of the field.
> >
> > 3. LabelAndMessageRenderer do this for render a Label an a field (please
> > look the parts in yellow)
> >
> >   private void _renderLabelCell(
> >     FacesContext        context,
> >     RenderingContext arc,
> >     UIComponent         component,
> >     FacesBean           bean,
> >     boolean             labelExists) throws IOException
> >   {
> >     ResponseWriter rw = context.getResponseWriter();
> >     rw.startElement("td", null);
> >
> >     // render labelStyleClass and defaultStyleClass.
> >     renderStyleClasses(context, arc, new String[]{
> >                        getLabelStyleClass(bean),
> >                        _getDefaultLabelStyleClass(arc,
> >                           SkinSelectors.AF_LABEL_TEXT_STYLE_CLASS )});
> >
> >     String labelInlineStyle = getLabelInlineStyleKey(bean);
> >     rw.writeAttribute("style", labelInlineStyle, null);
> >
> >     String valign = getDefaultLabelValign(bean);
> >
> >     rw.writeAttribute ("valign", valign, null);
> >     if (isDesktop(arc))
> >       rw.writeAttribute("nowrap", Boolean.TRUE, null);
> >
> >     if (labelExists)
> >     {
> >       rw.writeAttribute("width",
> >                         arc.getProperties().get(_LABEL_CELL_WIDTH_KEY),
> >                         null);
> >     }
> >
> >     delegateRenderer(context, arc, component, bean, _label);
> >     rw.endElement ("td");
> >   }
> >
> >   private void _renderFieldCell(
> >     FacesContext        context,
> >     RenderingContext arc,
> >     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);
> >     rw.writeAttribute("nowrap", Boolean.TRUE, null);
> >
> >     renderStyleClass(context, arc,
> > SkinSelectors.AF_CONTENT_CELL_STYLE_CLASS );
> >
> >     if (labelExists)
> >       rw.writeAttribute("width",
> >                         arc.getProperties().get(_FIELD_CELL_WIDTH_KEY),
> >                         null);
> >
> >     renderFieldCellContents(context, arc, 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, arc, component, bean))
> >       {
> >         rw.startElement("div", null);
> >         renderStyleClass(context, arc,
> >
> > SkinSelectors.AF_COMPONENT_MESSAGE_CELL_STYLE_CLASS);
> >         _renderMessageCellContents(context, arc, 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(arc) && isIE(arc))
> >     {
> >       rw.startElement("div", null);
> >       renderSpacer(context, arc, "1", "0");
> >       rw.endElement("div");
> >     }
> >
> >     rw.endElement("td");
> >   }
> >
> > I need to add an attribute in the td tag like <td colspan=2 rowspan=3
> > height=XXX width=XXX .........>, but if i want this, i need to
> > modify LabelAndMessageRenderer to recognize if the parent component is
> > my component, check if it has an attribute like this
> >
> >                     <mycomp:tableFormLayout labelWidth="100"
> > width="400" height="300"
> >                         fieldWidth="100" rows="100" columns="1*;1*;1*" >
> >                         <tr:selectOneChoice label="Salutation">
> >                             <f:selectItem itemLabel="1 Option"
> > itemValue="1" />
> >                             <f:attribute name="spanXItem" value="2"/>
> >                             <f:attribute name="spanYItem" value="3"/>
> >                         </tr:selectOneChoice>
> >                     </mycomp:tableFormLayout>
> >
> > and finally add a colspan or rowspan (height and width are optional).
> >
> > ---------
> > Conclusion?: It's necesary to decouple PanelFormLayoutRenderer and other
> > FormRenderers with LabelAndMessageRenderer in order to avoid
> > those hacks. I propose to create an interface that implements some
> > affected methods or create new ones, and delegate this rendering to the
> > parent
> > classes.
> >
> > I want to you what should be better to do in that case. If its necesary
> > to refactor the classes, how it can be done.
> >
> > Thanks for your attention
> >
> > regards
> >
> > Att: Leonardo Uribe
> > Ingeniero de Sistemas
> > Pontificia Universidad Javeriana
> > Ingeniero Electronico
> > Universidad Nacional de Colombia
> >
> >
> >
> >
> >
> >
> >
> >
>