myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Martin Marinschek" <martin.marinsc...@gmail.com>
Subject Re: [TRINIDAD] Decoupling Renderers (PanelFormLayoutRenderer and LabelAndMessageRenderer)
Date Sun, 10 Jun 2007 18:36:58 GMT
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 <dannyjrobinson@gmail.com> wrote:
> +1 (non-binding)
>
>
> On 6/6/07, Simon Lessard <simon.lessard.3@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

Mime
View raw message