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