Hi Simon,

This pattern was introduced to handle the case where we are using the same renderer to render different components, but we want to make sure the style classes that get rendered are for the correct component. If I'm writing a renderer for the XYZ component, and I want to use the menuBar renderer code, then I would map the menuBar style classes to XYZ style classes. That way I'll get XYZ style classes for my XYZ component.

If a renderer doesn't share rendering code, then they don't need to do this.

Another thing the renderer could do is to use renderer delegation. Then, the renderer could have a inner class that overrides the MenuBar renderer, for example, and overrides the methods which return style classes (this assumes there are appropriate hooks for this in the renderer you are overriding, which probably isn't the case)

I don't understand your grandparent example well enough to comment on it. First I wanted to be sure you understand what the purpose of this map is.

- Jeanne




Simon Lessard wrote:

Hello all,

It seems that most renderers use RenderingContext.setSkinResourceKeyMap to temporarily alter the skin selectors used by their children. The use case is
almost always :

Map original = RenderingContext.getSkinResourceKeyMap();
RenderingContext.setSkinResourceKeyMap(newMap);
// do some work
RenderingContext.setSkinResourceKeyMap(original);

I see three problems with that pattern.
First, there's no way to enforce it.

Secondly, it can lead to some unworking case. Imagine we have something
like:

<grand-parent>
 <parent>
   <child/>
 </parent>
</grand-parent>

Now let say child uses "af|component", "af|component::part" and
"af|component::part:state" selectors. Let assume that grand-parent redirects
"af|component" to "GrandParentReplacement" and parent redirects
"af|component::part" to "ParentReplacement" and "af|component::part:state"
to "af|component". The above pattern will result in the following
redirections:
- "af|component" --> not redirected
- "af|component::part" --> "ParentReplacement"
- "af|component::part:state" --> "af|component"

However, the above result is most likely not what was wanted. I believe it
should be more like:
- "af|component" --> "GrandParentReplacement"
- "af|component::part" --> "ParentReplacement"
- "af|component::part:state" --> "GrandParentReplacement"

So I would suggest to change setSkinResourceKeyMap to pushSkinResourceKeyMap
and add a popSkinResourceKeyMap as well as a peekSkinResourceKeyMap. The
selector resolution could then move through the whole redirection chain as
well as simplify the code required inside renderer. The above code would
become:

RenderingContext.pushSkinResourceKeyMap(newMap);
// do some work
RenderingContext.popSkinResourceKeyMap();

The third problem I see with this pattern is that parents has to know what
kind of children they will contain, which is really bad for the component
developers working outside Trinidad project but wanting to use its internal
feature (yes I know, that API is not currently public). I don't see any
solution to this problem yet, but I believe we should find a standardized
way to handle children selector redirection because some Trinidad components
seem a bit too strongly coupled together imho.


Regards,

~ Simon


Reply via email to