myfaces-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Gerhard Petracek" <gerhard.petra...@gmail.com>
Subject Re: [Skinning] Independent skinning myfaces subproject
Date Mon, 08 Dec 2008 15:52:28 GMT
hello paul,

in the past there were a lot of discussions concerning too much jar
dependencies. i personally prefer the independent approach (#2). anyway,
there are also other opinions out there so i also included the shared
approach for discussion purposes.

no - if we have a new jar dependency for trinidad i would suggest to
refactor it that trinidad is a myfaces skinning consumer as any other
project which uses this new project to provide skinning support.
which means: we should stop thinking that trinidad is the central part. in
such a case trinidad, tomahawk (hopefully tobago) and other libs or custom
components use the new project via the same api.

regards,
gerhard



2008/12/8 Paul Rivera <paul_mrivera@yahoo.com>

> Hi Gerhard,
>
> I'm not so clear on what the benefits of having the myfaces shared module
> approach (copy and repackage) for this specific situation with the shared
> skinning code.  Is it to avoid multiple versions of the shared skinning code
> in the classpath?  I think that chances that happening is less likely to
> occur compared to myfaces shared, considering that the shared skinning
> module is only shared between trinidad-core and the skinning project.
>
> The other option that we have is simply having the shared module as a
> dependency of the skinning project (shared-api, shared-impl).  Although, to
> be honest, having a shared-api/impl module makes me feel that the skinning
> project has not yet become fully independent.  Like it is still part of
> trinidad.  Better if we can find a way to remove it altogether.
>
> Another thing that I am looking into is what the behavior might be if a web
> project is using both trinidad(with skinning) and tomahawk(with skinning).
> Currently, tomahawk-support has a PhaseListener that initializes the
> SkinRenderingContext.  But trinidad is already doing that and tomahawk
> doesn't need to initialize it anymore.  Tomahawk just needs to render the
> skin styleClasses and leave the xss/css parsing and generation to trinidad.
>
> Best Regards,
> Paul Rivera
>
> --- On *Mon, 12/8/08, Gerhard Petracek <gerhard.petracek@gmail.com>*wrote:
>
> From: Gerhard Petracek <gerhard.petracek@gmail.com>
> Subject: Re: [Skinning] Independent skinning myfaces subproject
> To: "MyFaces Development" <dev@myfaces.apache.org>, paul_mrivera@yahoo.com
> Date: Monday, December 8, 2008, 1:22 AM
>
>
> hello paul,
>
> ok - let's continue with the case you mentioned.
>
> we could:
>  - use the same approach of the myfaces shared module also for the shared
> skinning code
>  - provide skinning as an independent jar file (it's easier for other
> projects/custom components to re-use it)
>
> regards,
> gerhard
>
>
>
> 2008/12/8 Paul Rivera <paul_mrivera@yahoo.com>
>
>>  Hi,
>>
>> It's good to hear that there's effort done to make skinning standardized
>> and part of JSF by Simon.  Is there anything that the current skinning
>> project we have at http://code.google.com/p/myfaces-csi/ can contribute
>> to this?
>>
>> In the event that Simon's ideas don't get integrated into JSF 2.0, I'd
>> like to bring back the discussion to the skinning project that we now have
>> in the link mentioned above.
>>
>> Overall, I think the community agrees with the idea of having an
>> independent skinning project that is basically derived from trinidad code.
>> I'd like to hear your opinion on the project layout described in
>> http://code.google.com/p/myfaces-csi/wiki/MyfacesSkinsProposal.
>>
>> What concerns me most here is that the skins project and trinidad share a
>> lot of classes that it is hard to get a clean separation.  You can check
>> shared-impl for those classes.
>>
>> Our current layout has a shared module (shared-api, shared-impl).  This
>> module contains code shared by both skinning and trinidad-core.  We can
>> probably move some of the utility classes into myfaces-commons-utils.  But
>> other classes there might not be such a good fit into myfaces-commons-utils.
>>
>> We started this project with the most immediate goal of giving tomahawk
>> skinning support and eventually have trinidad use this project.  We've taken
>> trinidad skinning code and now it works with tomahawk and trinidad-core.  In
>> the event that this project gets accepted into myfaces, integration with
>> tomahawk is not a big problem.  I am actually more worried with the changes
>> we have to make in trinidad-core.  This is why I'd like to propose as a
>> roadmap:
>>   - finish the skinning project and make the necessary changes in
>> trinidad-core without adding new features yet to the current set that
>> trinidad has.  There will be big changes in trinidad-core that need to be
>> done at the same time.
>>   - once we verify that everything is working, we can then add the desired
>> new features/changes to the skinning api.  In this phase, we can implement
>> the new features/changes to the api in small and more manageable increments.
>>
>> While Simon is in the process of submitting his proposal, I'd like to work
>> on these issues and anything else you think might be a problem for the
>> skinning project or the transition with trinidad.
>>
>> Best Regards,
>> Paul Rivera
>>
>> --- On *Sat, 12/6/08, Gerhard Petracek <gerhard.petracek@gmail.com>*wrote:
>>
>> From: Gerhard Petracek <gerhard.petracek@gmail.com>
>> Subject: Re: [Skinning] Independent skinning myfaces subproject
>> To: "MyFaces Development" <dev@myfaces.apache.org>
>> Date: Saturday, December 6, 2008, 12:42 PM
>>
>>
>> hello simon,
>>
>> no it's just because of ie version < 7 like it is mentioned in the
>> trinidad skinning documentation.
>>
>> regards,
>> gerhard
>>
>>
>>
>> 2008/12/6 Simon Lessard <simon.lessard.3@gmail.com>
>>
>>> Hi Gerhard,
>>>
>>> Trinidad already has this and it would be the same with what I propose.
>>> Assume: <tr:tree styleClass="MyClass"/>
>>>
>>> Then switch the selectors to: tr|tree.MyClass
>>>
>>> As far as I can tell this is enough to cover every possibilities without
>>> burdening the framework with an extra attribute. Unless you can come up with
>>> a counter example not involving IE6's shitty CSS support.
>>>
>>>
>>> ~ Simon
>>>
>>>
>>> On Sat, Dec 6, 2008 at 2:19 PM, Gerhard Petracek <
>>> gerhard.petracek@gmail.com> wrote:
>>>
>>>> hello simon,
>>>>
>>>> in my opinion andrew brought up an interesting question. have you also
>>>> thought about multiple selectors for the same component?
>>>>
>>>> i repeat the example i mentioned before:
>>>>
>>>> <tr:tree/> ... uses default selector
>>>> <tr:tree selectorId="myId"/> ... uses selector with "myId" to use a
>>>> different selector
>>>>
>>>> regards,
>>>> gerhard
>>>>
>>>>
>>>>
>>>> 2008/12/6 Simon Lessard <simon.lessard.3@gmail.com>
>>>>
>>>> Hi all,
>>>>>
>>>>> Since I completed the proposition by memory yesterday I forgot some
>>>>> important parts. Also, I thought more about some possibilities I rejected
>>>>> during the night and reconsidered my those. So here is v2. Among other
thing
>>>>> I integrated skin extends, removed selector redirection, removed some
other
>>>>> PENDING and simplified 3.1 suggestion since I discarded redirection:
>>>>>
>>>>> *Modified classes*
>>>>>
>>>>> public abstract class Application
>>>>> {
>>>>>     public String getDefaultSkinFamily();
>>>>>     public void setDefaultSkinFamily(String skinFamily);
>>>>> }
>>>>>
>>>>> public final class FactoryFinder
>>>>> {
>>>>>     public static final String SKIN_FACTORY;
>>>>> }
>>>>>
>>>>> public class UIViewRoot
>>>>> {
>>>>>     public String getSkinFamily();
>>>>>     public void setSkinFamily(String skinFamily);
>>>>> }
>>>>>
>>>>>
>>>>> *Modified methods*
>>>>>
>>>>> public abstract class ViewHandler
>>>>> {
>>>>>     /**
>>>>>      * Same as before but also copy skin family.
>>>>>      */
>>>>>     public abstract UIViewRoot createView(FacesContext context, String
>>>>> viewId);
>>>>> }
>>>>>
>>>>>
>>>>> *New classes*
>>>>>
>>>>> public abstract class Icon extends Resource
>>>>> {
>>>>>     /**
>>>>>      * Gets the key within the skin's ResourceBundle to the description
>>>>> of this icon. The description can be used
>>>>>      * as an alternate text for the icon to improve accessibility for
>>>>> example.
>>>>>      */
>>>>>     public abstract String getDescriptionKey();
>>>>>
>>>>>     /**
>>>>>      * Gets the name of this icon.
>>>>>      */
>>>>>     public abstract String getName();
>>>>>
>>>>>     /**
>>>>>      * Gets the effective style class of this icon within the skin.
>>>>>      */
>>>>>     public abstract String getStyleClass();
>>>>> }
>>>>>
>>>>> public abstract class Skin
>>>>> {
>>>>>     public abstract Resource getContentResource(FacesContext context);
>>>>>
>>>>>     public abstract Icon getIcon(FacesContext context, String
>>>>> iconName);
>>>>>
>>>>>     public abstract Object getProperty(FacesContext context, String
>>>>> propertyName);
>>>>>
>>>>>     /**
>>>>>      * Get the ResourceBundle for this skin in the current locale.
>>>>>      */
>>>>>      public abstract ResourceBundle getResourceBundle(FacesContext
>>>>> context);
>>>>>
>>>>>     public abstract SkinNode getSkinNode(FacesContext context, SkinSelector
>>>>> selector);
>>>>>
>>>>>     public String getStyleClass(FacesContext context, SkinSelector
>>>>> selector)
>>>>>     {
>>>>>         SkinNode node = getSkinNode(context, selector);
>>>>>         return node == null ? null : node.getStyleClass();
>>>>>     }
>>>>> }
>>>>>
>>>>> public class SkinException extends FacesException
>>>>> {
>>>>>     // Provides all 4 common Exception constructors
>>>>> }
>>>>>
>>>>> public abstract class SkinFactory implements FacesWrapper<SkinFactory>
>>>>> {
>>>>>     public abstract void addSkin(String skinFamily, String renderKitId,
>>>>> Skin skin);
>>>>>     public abstract Skin getSkin(String skinFamily, String renderKitId
>>>>> );
>>>>>     public abstract Collection<String> getSkinFamilies();
>>>>>     public SkinFactory getWrapped()
>>>>>     {
>>>>>         return null;
>>>>>     }
>>>>> }
>>>>>
>>>>> public class SkinInitializationException extends SkinException
>>>>> {
>>>>>     // Provides all 4 common Exception constructors
>>>>> }
>>>>>
>>>>> /**
>>>>>  * Implementations of this interface are in charge of creating Skin
>>>>> instances in an implementation specific manner.
>>>>>  */
>>>>> public interface SkinLoader
>>>>> {
>>>>>     /**
>>>>>      * Creates a new <code>Skin</code> instance the specified
>>>>> skinFamily and parameters. There's no garanteed as of what
>>>>>      * parameters will be present in the Map argument and the creation
>>>>> should fails if those parameters are not correct
>>>>>      * for the specific implementation.
>>>>>      *
>>>>>      * @throws SkinInitializationException if the provided parameters
>>>>> are not sufficient to create the new <code>Skin</code>
>>>>>      *         instance
>>>>>      */
>>>>>     public Skin loadSkin(Skin parentSkin, String resourceBundle,
>>>>> Map<String, String> parameters);
>>>>> }
>>>>>
>>>>> public abstract class SkinNode
>>>>> {
>>>>>     public abstract String getStyleClass();
>>>>>
>>>>>     public abstract Map<String, Object> getProperties();
>>>>>
>>>>>     /**
>>>>>      * Gets a server side property of this node. Server side properties
>>>>> are not visible by the client.
>>>>>      */
>>>>>     public Object getProperty(String propertyName)
>>>>>     {
>>>>>         return getProperties().get(propertyName);
>>>>>     }
>>>>>
>>>>>     /**
>>>>>      * Gets a read-only version of the client-side properties of this
>>>>> node. In HTML, those represent CSS properties.
>>>>>      *
>>>>>      * It's valid to place those properties in a SoftRenderece for
>>>>> memory footprint safety. However, this
>>>>>      * method must be able to reload them if needed
>>>>>      * those properties should be placed in memory-aware renference
>>>>>      */
>>>>>     public abstract Map<String, Object> getStyleProperties();
>>>>>
>>>>>     public Object getStyleProperty(String propertyName)
>>>>>     {
>>>>>         return getStyleProperties().get(propertyName);
>>>>>     }
>>>>> }
>>>>>
>>>>> public class SkinSelector implements Comparable<SkinSelector>
>>>>> {
>>>>>     /**
>>>>>      * Finds the SkinSelector with the specified name or return
>>>>> <code>null</code> if it doesn't exists. This
>>>>>      * method should be called by Renderers during their initialization
>>>>> in order to cache the SkinSelector instances
>>>>>      * they'll be using to increase overall performance of the Skin
>>>>> module.
>>>>>      */
>>>>>     public static SkinSelector getInstance(String selectorName);
>>>>>
>>>>>     /**
>>>>>      * Finds the SkinSelector with the specified name or create a new
>>>>> one if it doesn't exists and <code>create</code>
>>>>>      * argument is <code>true</code>. This method should
be used mainly
>>>>> by SkinLoader in order to register a new
>>>>>      * selector.
>>>>>      */
>>>>>     public static SkinSelector getInstance(String selectorName,
>>>>> boolean create);
>>>>>
>>>>>     private static int nextOrdinal = 0;
>>>>>
>>>>>     private int ordinal;
>>>>>     private String name;
>>>>>
>>>>>     private SkinSelector(String name)
>>>>>     {
>>>>>         assert name != null;
>>>>>
>>>>>         synchronized (SkinSelector.class)
>>>>>         {
>>>>>             ordinal = nextOrdinal++;
>>>>>         }
>>>>>
>>>>>         this.name = name;
>>>>>     }
>>>>>
>>>>>     public boolean equals(Object obj)
>>>>>     {
>>>>>         // Sufficient because ordinal is unique
>>>>>         return o == this;
>>>>>     }
>>>>>
>>>>>     public int hashCode()
>>>>>     {
>>>>>         return ordinal();
>>>>>     }
>>>>>
>>>>>     public String name()
>>>>>     {
>>>>>         return name;
>>>>>     }
>>>>>
>>>>>     public int ordinal()
>>>>>     {
>>>>>         return ordinal;
>>>>>     }
>>>>> }
>>>>>
>>>>> *New config
>>>>> *<application>
>>>>>   <default-skin-family/>
>>>>> </application>
>>>>> <skin>
>>>>>   <skin-family/>
>>>>>   <render-kit-id/>
>>>>>   <description/>
>>>>>   <extends>
>>>>>     <skin-family/>
>>>>>     <render-kit-id/>
>>>>>   </extends>
>>>>>   <skin-loader-class/>
>>>>>   <resource-bundle/>
>>>>>   <skin-loader-parameters>
>>>>>     <map-entries/>
>>>>>   </skin-loader-parameters>
>>>>> </skin>
>>>>> *
>>>>> *
>>>>> PENDING: Should it instead be a getTranslatedResource instead of
>>>>> getResourceBundle within the Skin class?
>>>>>
>>>>> PENDING: Should the skin family and render kit id passed to the loader
>>>>> or is that irrelevant?
>>>>>
>>>>> PENDING: With the proposed API, Trinidad aliases wouldn't be able to
be
>>>>> used across skin additions as it would be aggregated in a CompositeSkin
>>>>> instance and thus in multiple different documents, anyone has a better
idea
>>>>> than CompositeSkin for this? Maybe stardadize aliases somehow and have
>>>>> CompositeSkin aggregate the content in a single document instead of
>>>>> delegating to its fragments?
>>>>>
>>>>> PENDING: Should Skin.getIcon uses an optimized key as well? Doesn't
>>>>> seem required since there are much less icons in a page than HTML elements,
>>>>> thus the gain wouldn't worth the trouble imho.
>>>>>
>>>>> PENDING: The Resource API might have to be revisited in order to
>>>>> recognize the Resource returned by Skin.getContentResource so that
>>>>> ResourceHandler can identify Resource requests for the skin content and
thus
>>>>> locate the given skin, get its Resource insteance and return the content
>>>>> with the standard algorithm. I believe a reserved library name could
be used
>>>>> for that, the resource name is an harder issue though since the skin
>>>>> identifier is a tuple atm and defining a reserved separator character
would
>>>>> bring limitation to the render kit ids and skin family values. Someone
could
>>>>> come up with a better suggestion for that maybe?
>>>>>
>>>>> PENDING: Skin.getStyleProperties could maybe offer the option to return
>>>>> a mutable Map as an optional feature, but then would requires the Skin
to
>>>>> regenerate the style document (CSS). However this can get hellish with
>>>>> composite skin. The node would need to have access to its container Skin
and
>>>>> there should be a SkinModificationEvent/Listener capability added to
the
>>>>> Skin class.
>>>>>
>>>>>
>>>>> Regards,
>>>>>
>>>>> ~ Simon
>>>>>
>>>>>
>>>>> On Fri, Dec 5, 2008 at 1:21 PM, Simon Lessard <
>>>>> simon.lessard.3@gmail.com> wrote:
>>>>>
>>>>>> I agree with most of these statements, but I would start even higher
>>>>>> than that, like defining the base interfaces and access classes.
>>>>>>
>>>>>> For instance, I think it's safe to assume that a Skin class or
>>>>>> interface should exists. Let assume all interfaces for now as it
takes less
>>>>>> characters. Now, from where and how should the Skin be available
for a given
>>>>>> FacesContext. Personally I believe a Skin should be linked to a RenderKit
>>>>>> (or a common base RenderKit class for all MyFaces extensions if not
in the
>>>>>> standard), but let assume work on the API for now for the sake of
the
>>>>>> discussion.
>>>>>>
>>>>>> So for now we have:
>>>>>>
>>>>>> public interface Skin
>>>>>> {
>>>>>>     public String getResourceBundle();
>>>>>> }
>>>>>>
>>>>>> public abstract class RenderKit
>>>>>> {
>>>>>>     public abstract Skin getSkin(FacesContext context);
>>>>>> }
>>>>>>
>>>>>> So far so good, but now that opens some issues that will themselves
>>>>>> explode into more:
>>>>>>
>>>>>>    1. Should the way the RenderKit locates the current Skin
>>>>>>    standardized?
>>>>>>    2. How do we define the contract ensuring that the Skin get
>>>>>>    rendered on the page?
>>>>>>    3. What other functionalities should be standarized in the Skin
>>>>>>    interface?
>>>>>>
>>>>>> *Issue 1: Current skin localization*
>>>>>> Personally I chose yes to that question since it allow a standardized
>>>>>> way to define skins. Let use Trinidad's skin-family notion here,
but with
>>>>>> the way renderKitId is defined, that's the view root and a factory
>>>>>> implementing decorator pattern. So we add
>>>>>>
>>>>>> public class UIViewRoot
>>>>>> {
>>>>>>     public String getSkinFamily();
>>>>>>     public void setSkinFamily(String skinFamily);
>>>>>> }
>>>>>>
>>>>>> public abstract class SkinFactory implements FacesWrapper<SkinFactory>
>>>>>> {
>>>>>>     public abstract void addSkin(String skinFamily, String
>>>>>> renderKitId, Skin skin);
>>>>>>     public abstract Skin getSkin(String skinFamily, String
>>>>>> renderKitId);
>>>>>>     public abstract Collection<String> getSkinFamilies();
>>>>>>     public SkinFactory getWrapped()
>>>>>>     {
>>>>>>         return null;
>>>>>>     }
>>>>>> }
>>>>>>
>>>>>> *Sub-issue 1.1: Default SkinFactory implementation behavior*
>>>>>> Additional Exceptions
>>>>>> public class SkinException extends FacesException
>>>>>> {
>>>>>>     // Provides all 4 common Exception constructors
>>>>>> }
>>>>>>
>>>>>> public class SkinInitializationException extends SkinException
>>>>>> {
>>>>>>     // Provides all 4 common Exception constructors
>>>>>> }
>>>>>>
>>>>>> Additional interface
>>>>>> /**
>>>>>>  * Implementations of this interface are in charge of creating Skin
>>>>>> instances in an implementation specific manner.
>>>>>>  */
>>>>>> public interface SkinLoader
>>>>>> {
>>>>>>     /**
>>>>>>      * Creates a new <code>Skin</code> instance the specified
>>>>>> skinFamily and parameters. There's no garanteed as of what
>>>>>>      * parameters will be present in the Map argument and the creation
>>>>>> should fails if those parameters are not correct
>>>>>>      * for the specific implementation.
>>>>>>      *
>>>>>>      * @throws SkinInitializationException if the provided parameter
>>>>>> are not enough to create the <code>Skin</code> instance
>>>>>>      */
>>>>>>     public Skin loadSkin(String skinFamily, String resourceBundle,
>>>>>> Map<String, String> parameters);
>>>>>> }
>>>>>>
>>>>>> Addition to faces-config.xml:
>>>>>> <application>
>>>>>>   <default-skin-family/>
>>>>>> </application>
>>>>>> <skin>
>>>>>>   <skin-family/>
>>>>>>   <render-kit-id/>
>>>>>>   <description/>
>>>>>>   <skin-loader-class/>
>>>>>>   <resource-bundle/>
>>>>>>   <skin-loader-parameters>
>>>>>>     <map-entries/>
>>>>>>   </skin-loader-parameters>
>>>>>> </skin>
>>>>>>
>>>>>> Note that this solution makes RenderKit.getSkin more an utility method
>>>>>> than anything, except if an extension decides to override it (would
probably
>>>>>> be the casew ith Trinidad, at least to start to use trinidad-config.xml,
or
>>>>>> later to add .pda or .desktop to the current skinFamily).
>>>>>>
>>>>>> Also, the framework should probably provide some implementations
of
>>>>>> SkinLoader out-of-the-box, most likely ClassSkinLoader expecting
a skinClass
>>>>>> parameter and a CSSSkinLoader receiving a cssResourcePath parameter.
>>>>>> (Trinidad would mostl ikely provide an XSSSkinLoader for example)
>>>>>>
>>>>>> *Issue 2: Skin content rendering*
>>>>>> How should rendering be handled? Should it be handled as an added
>>>>>> ResourceDependency just before rendering or as an additional contract
for
>>>>>> the default HtmlRenderer for HtmlHead? The latter sounds better,
but how
>>>>>> should it be implemented? target would obviously be "head", but then
a
>>>>>> public Resource Skin.getContentResource() method could be required
and this
>>>>>> might imply some changes to the ResourceHandler specification so
that it can
>>>>>> locate the Skin instance in order to be able to serve the Resource's
content
>>>>>> (effective CSS content) to the agent. I like the Resource version,
but I
>>>>>> have more thinking to do about how to implement this, maybe involving
a
>>>>>> reserved resourceIdentifier structure/syntax
>>>>>>
>>>>>> *Issue 3: Skin features*
>>>>>> Additional class
>>>>>> public abstract class Icon extends Resource
>>>>>> {
>>>>>>     /**
>>>>>>      * Gets the key within the skin's ResourceBundle to the
>>>>>> description of this icon. The description can be used
>>>>>>      * as an alternate text for the icon to improve accessibility
for
>>>>>> example.
>>>>>>      */
>>>>>>     public abstract String getDescriptionKey();
>>>>>>
>>>>>>     /**
>>>>>>      * Gets the name of this icon.
>>>>>>      */
>>>>>>     public abstract String getName();
>>>>>>
>>>>>>     /**
>>>>>>      * Gets the effective style class of this icon within the skin.
>>>>>>      */
>>>>>>     public abstract String getStyleClass();
>>>>>> }
>>>>>>
>>>>>> public interface Skin
>>>>>> {
>>>>>>     public Icon getIcon(String iconName);
>>>>>>
>>>>>>     public String getProperty(String propertyKey);
>>>>>>
>>>>>>     public String getResourceBundle();
>>>>>>
>>>>>>     public String getStyleClass(String selectorKey);
>>>>>> }
>>>>>>
>>>>>> *Sub-issue 3.1: style class / property / icon access strategy*
>>>>>> Trinidad uses String keys to access style classes within the skin.
>>>>>> That strategy is very flexible, but alas very slow, thanks to
>>>>>> String.hashCode() being linear and uncached. So, even if String.intern()
is
>>>>>> called on all selectors within a given skin, the gain will only be
on
>>>>>> String.equals, making it O(1) instead of O(n). Even if this is better
than
>>>>>> nothing, especially it there's a collision, the overall complexity
of
>>>>>> looking up a selector remains O(n) with the length of the key. So,
the
>>>>>> overall cost of skinning with this strategy is averageLengthOfKey
*
>>>>>> averageAmountOfComponentPerPage * averageAmountOfHtmlElementPerComponent
>>>>>> (assuming each element gets its own style class which is required
for
>>>>>> maximum customizability). Another, but a little bit more complex,
solution
>>>>>> is also possible using a "dynamic enum" alike to PropertyKey in Trinidad.
So
>>>>>> I'd like something like:
>>>>>>
>>>>>> public abstract class SkinKeyPart
>>>>>> {
>>>>>>     public String name();
>>>>>>
>>>>>>     public int ordinal();
>>>>>> }
>>>>>>
>>>>>> public class Namespace extends SkinKeyPart
>>>>>> {
>>>>>>     /**
>>>>>>      * Find or create the Namespace instance with the specified name.
>>>>>>      */
>>>>>>     public static Namespace getInstance(String name);
>>>>>> }
>>>>>>
>>>>>> public class ComponentKey extends SkinKeyPart
>>>>>> {
>>>>>>     /**
>>>>>>      * Find or create the ComponentKey instance with the specified
>>>>>> name.
>>>>>>      */
>>>>>>     public static ComponentKey getInstance(String name);
>>>>>> }
>>>>>>
>>>>>> public class ComponentPartKey extends SkinKeyPart
>>>>>> {
>>>>>>     /**
>>>>>>      * Find or create the ComponentPartKey instance with the
>>>>>> specified name.
>>>>>>      */
>>>>>>     public static ComponentPartKey getInstance(String name);
>>>>>> }
>>>>>>
>>>>>> public class ComponentStateKey extends SkinKeyPart
>>>>>>  {
>>>>>>     /**
>>>>>>      * Find or create the ComponentStateKey instance with the
>>>>>> specified name.
>>>>>>      */
>>>>>>     public static ComponentPartKey getInstance(String name);
>>>>>> }
>>>>>>
>>>>>> public abstract class SkinNode
>>>>>> {
>>>>>>     public abstract String[] getStyleClasses();
>>>>>>     public abstract String getProperty(String propertyName);
>>>>>>     public abstract Icon getIcon(String iconName);
>>>>>>     public abstract SkinNode getSubPart(ComponentPartKey partKey);
>>>>>> }
>>>>>>
>>>>>> public interface Skin
>>>>>> {
>>>>>>     /**
>>>>>>      * Still exists to get properties global to the whole skin if
>>>>>> someone ever need that feature
>>>>>>      */
>>>>>>     public String getProperty(String propertyName);
>>>>>>
>>>>>>     /**
>>>>>>      * No change here
>>>>>>      */
>>>>>>     public String getResourceBundle();
>>>>>>
>>>>>>     public String getSkinNode(Namespace ns, ComponentKey component);
>>>>>>
>>>>>>     public String getSkinNode(Namespace ns, ComponentKey component,
>>>>>> ComponentStateKey state);
>>>>>>
>>>>>>     public String getSkinNode(Namespace ns, ComponentKey component,
>>>>>> ComponentStateKey... states);
>>>>>> }
>>>>>>
>>>>>> That solution has the advantage of being very fast, actually a real
>>>>>> O(1) for every node access assuming the Renderer gathers the keys
it needs
>>>>>> during instanciation. Then the "root" SkinNode could probably be
located
>>>>>> using a base Renderer class and passed to a custom encoding method
>>>>>> (Trinidad's encodeAll for example). Of course, the skin loaders would
have
>>>>>> to create skin instances structuring the selectors accordingly. A
base class
>>>>>> for Skin with such feature should probably be provided if this solution
is
>>>>>> wanted in order to make new implementation of Skin easier to create.
>>>>>>
>>>>>> *PENDIND issues:*
>>>>>> PENDING: Should the path leverage the Resource API instead and receive
>>>>>> a library-name, library-version, resource-name and resource-version
instead?
>>>>>>
>>>>>> PENDING: A CompositeSkin class should probably be provided and most
>>>>>> likely usable from the configuration, should it be using a specific
loader
>>>>>> with parameters or have a fully-fledged tag like <composite-skin>
for
>>>>>> example? The use of such skin implementation would be for users using
>>>>>> multiple libraries, each with very different RenderKit implementations.
A
>>>>>> composite RenderKit class could also be useful here.
>>>>>>
>>>>>> PENDING: Should Trinidad's SkinAddition notion be considered?
>>>>>> SkinAddition provides a way to add skin elements to an existing skin
based
>>>>>> on its id. It would be possible to leverage that by using the
>>>>>> skin-family/render-kit-id tuple instead. Another option would be
to simply
>>>>>> have the default SkinFactory implementation to automatically agreggate
the
>>>>>> Skin instances with the same skin-family and render-kit-id into a
>>>>>> CompositeSkin instance.
>>>>>>
>>>>>> PENDING: Should additional metadata be added to <renderer>
tag to
>>>>>> define the supported skin selector for tooling purpose? This point
is
>>>>>> dependant on the content of the Skin interface and the strategy chosen
to
>>>>>> access the properties/style class of a given component and/or one
of its
>>>>>> sub-element.
>>>>>>
>>>>>> PENDING: Should the effective CSS properties stay accessible in memory
>>>>>> or otherwise from the Skin instance? If so, should they be modifiable?
I
>>>>>> tend toward no for both for performance issues. Of course this could
be also
>>>>>> left as an optional operation of the interface, throwing
>>>>>> UnsupportedOperationException in most case but at least leaving the
>>>>>> possibility for special implementations requiring it. This point
also impact
>>>>>> issue 2 in some ways.
>>>>>>
>>>>>> PENDING: About Icon, it should probably also leverage the Resource
>>>>>> API, how should that be implemented?
>>>>>>
>>>>>> PENDING: Icon's styleClass, should the instance directly return an
>>>>>> effective class or should it rather return a selector that would
then be
>>>>>> looked up from the Skin? I prefer the latter, but then there's the
Stirng
>>>>>> issue so maybe the icon would have to return an optimized selector
key as
>>>>>> mentioned in 3.1
>>>>>>
>>>>>> PENDING: Solution to issue 3.1, although very fast and flexible,
can
>>>>>> be an linkage nightmare. For example, a node for component "inputText"
with
>>>>>> states "disabled" and "required" should be able to link to the component
>>>>>> part node for part "label" of "inputText" without any state defined
if
>>>>>> needed. The performance gain of 3.1 is great, the implementation
complexity
>>>>>> isn't. Still, personally I don't have any problem throwing complexity
at
>>>>>> implementor's head if the users can feel the difference. Another
option
>>>>>> would be to remove the "state" complexity part and have a predefined
style
>>>>>> class syntax for those. That solution is what Trinidad does. However,
this
>>>>>> solution is not as flexible as it doesn't allow to switch Icon dynamically
>>>>>> depending on the component's state.
>>>>>>
>>>>>> PENDING: Solution 3.1 don't allow state to be applied on the
>>>>>> component's sub parts. Most of the time it's not an issue, but we
have one
>>>>>> such use case with Trinidad's train component where the train itself
doesn't
>>>>>> have a state, but each of its station (sub-part) can be visited/unvisited
>>>>>> and/or selected and/or disabled. If 3.1 is kept, should it be tweaked
even
>>>>>> more to allow a sub-part state on a per part basis as well? This
makes the
>>>>>> linkage a nightmare on Elm Street candidate, althoguh adding more
potential
>>>>>> to the Skin
>>>>>>
>>>>>> PENDING: Trinidad supports a "selector redirect" feature that is
used
>>>>>> with the delegate renderer architecture to have specified selectorKeys
>>>>>> transformed into a different one. This is implemented as a Map<String
>>>>>> oldName, String newName> redirection map. Should such feature
be
>>>>>> standardized? If so and 3.1 is adressed then it will have to be well
thought
>>>>>> about. Also, trinidad support a single of those map applied as a
set on the
>>>>>> skin instance, I believe it should be a push / pop instead if standardized.
>>>>>>
>>>>>> PENDING: Should there be any inheritance/cascading behavior defined
by
>>>>>> default? I tend toward no here.
>>>>>>
>>>>>> PENDING: Should the skin have a getTranslatedResource(FacesContext
>>>>>> context, String resourceKey) instead of the getResourceBundle method?
>>>>>>
>>>>>>
>>>>>> That's about it for now. My main blocker is 3.1 and I'd like to come
>>>>>> up with something better for it before presenting it to the EG, same
holds
>>>>>> true with various links to the Resource API (icons, the skin itself,
etc)
>>>>>>
>>>>>>
>>>>>> Regards,
>>>>>>
>>>>>> ~ Simon
>>>>>>
>>>>>>
>>>>>>
>>>>>> On Fri, Dec 5, 2008 at 10:33 AM, Andrew Robinson <
>>>>>> andrew.rw.robinson@gmail.com> wrote:
>>>>>>
>>>>>>> > All other frameworks use
>>>>>>> > component attributes for this, but Trinidad puts it in these
>>>>>>> > non-intuitive skinning keys.
>>>>>>>
>>>>>>> Sorry, had one more comment right after I hit send again. Maybe
just
>>>>>>> having default component attributes for a web app would satisfy
the
>>>>>>> need. Like a way to say 'partialSumbit' should be defaulted to
true
>>>>>>> on
>>>>>>> all tr:commandLink. Then all the skin properties could be converted
>>>>>>> to
>>>>>>> attributes and have their defaults set in a common location (like
>>>>>>> what
>>>>>>> the skin does).
>>>>>>>
>>>>>>> This would be much more useful and flexible as then page developers
>>>>>>> can make exceptions to the rule.
>>>>>>>
>>>>>>
>>>>>>
>>>>>
>>>>
>>>>
>>>> --
>>>>
>>>> http://www.irian.at
>>>>
>>>> Your JSF powerhouse -
>>>> JSF Consulting, Development and
>>>> Courses in English and German
>>>>
>>>> Professional Support for Apache MyFaces
>>>>
>>>
>>>
>>
>>
>> --
>>
>> http://www.irian.at
>>
>> Your JSF powerhouse -
>> JSF Consulting, Development and
>> Courses in English and German
>>
>> Professional Support for Apache MyFaces
>>
>>
>>
>
>
> --
>
> http://www.irian.at
>
> Your JSF powerhouse -
> JSF Consulting, Development and
> Courses in English and German
>
> Professional Support for Apache MyFaces
>
>
>


-- 

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