On Tue, Dec 9, 2008 at 2:23 PM, Gerhard Petracek
<[EMAIL PROTECTED]> wrote:
> hello,
>
> concerning the accessibility mode: is trinidad tested with real
> screen-readers?
we use jaws
> furthermore, we should specify if we are talking about skinning or theming.
>
> regards,
> gerhard
>
>
>
> 2008/12/9 Paul Rivera <[EMAIL PROTECTED]>
>>
>> Hi,
>>
>> I agree with Jeanne as well regarding the requirements. This has been the
>> list of requirements we've used as a guide in building the skinning
>> project. Maybe we can use this as a starting point. Feel free to modify
>> the list.
>>
>> from trinidad:
>> * basic css style skinning
>> * global styles/aliases
>> * skin extensions
>> * skin additions for custom component developers
>> * properties skinning
>> * icon skinning
>> * text skinning / translations
>> - using bundle-name
>> - using translation-source
>> * skin variants based on:
>> - agent name
>> - agent version
>> - platform name
>> - accessibility-profile
>> - direction (:rtl)
>> - locale (@locale, :lang) -> Accdg to the skinning guide, this is not
>> yet implemented in trinidad
>> * dynamically changing skins at runtime
>> * compressed styleclass names feature
>> * CHECK_FILE_MODIFICATION feature
>> * And as Jeanne mentioned, compatibility with portals. I don't have much
>> experience with portals. I will probably need to look more into this.
>>
>> added requirements:
>> * tomahawk-support: make use of AddResource and ExtensionsFilter
>> * generic-support
>>
>> As for simon's issue on style class / property / icon access strategy
>> (sub-issue 3.1), I've read somewhere that hashcode is already cached in
>> String since java 1.3. I've not really verified this on java 1.3. But I
>> did check on jdk 1.6 and confirmed that it does cache hashcode. Here's the
>> snippet fro java.lang.String:
>>
>> public int hashCode() {
>> int h = hash;
>> if (h == 0) {
>> int off = offset;
>> char val[] = value;
>> int len = count;
>>
>> for (int i = 0; i < len; i++) {
>> h = 31*h + val[off++];
>> }
>> hash = h;
>> }
>> return h;
>> }
>>
>> Best Regards,
>> Paul Rivera
>>
>> --- On Tue, 12/9/08, Matthias Wessendorf <[EMAIL PROTECTED]> wrote:
>>
>> From: Matthias Wessendorf <[EMAIL PROTECTED]>
>> Subject: Re: [Skinning] Independent skinning myfaces subproject
>> To: "MyFaces Development" <[email protected]>
>> Date: Tuesday, December 9, 2008, 12:52 AM
>>
>> On Tue, Dec 9, 2008 at 1:03 AM, Jeanne Waldman
>> <[EMAIL PROTECTED]> wrote:
>> >
>> What about Step A - requirements? We should list out the requirements we
>> > have so we can make sure we aren't missing anything. There's been
>> a lot of
>> > work in getting the skinning to work with portals, so we'll need that
>>
>> to
>> > still work and we will probably want to redesign it since it's kind of
>> lame
>> > the way it works right now.
>>
>> +1
>> good point, Jeanne, we don't want to see that work destroyed.
>>
>> -M
>>
>>
>> >
>> > From my experience coming up with a good API takes a lot of time. I'll
>> try
>> > to find some time to read your proposal at least.
>> >
>> > Jeanne
>> >
>> > Simon Lessard wrote, On 12/8/2008 6:16 AM PT:
>>
>> >>
>> >> I would prefer a roadmap like:
>> >>
>> >> 1. Design a modular API that fits Trinidad's needs with minimal
>> >> compatibility loss.
>> >> 2. In parallel
>> >> 1. Start implementing the API defined in 1.
>> as a myfaces
>> >> extension, possibily along with a ResourceHandler for JSF
>> 1.2
>> >> 2. Propose the API to JSF 2.0 EG
>> >> 3. If the API make it the the spec then
>> >> 1. Convert the extension to fit the new API (even if target
>>
>> >> is 1.2 it should be possible but in a different package)
>> >> 2. Integrate the API with the corect package naming to the
>> >> 2.0 branch (obviously)
>> >> 4. In the API doesn't get in the spec, then create a 2.0 branch
>>
>> of
>> >> the skin extension
>> >> 5. Convert Trinidad to the new extension
>> >> 6. Integrate the extension in Tomahawk and Tobago
>> >>
>> >>
>> >> So, for now, I would really really like to get comments from the
>>
>> community
>> >> on the API I proposed as well as potential solutions for the pendings.
>> >> Otherwise I'll have to
>> propose it in its current form and that
>> would prevent
>> >> the API to be reviewed by the MyFaces community and that would be a
>> shame
>> >> imho. As I mentioned before, time is running really short and the fact
>>
>> that
>> >> 2.0 is in public review phase alone might prevent the addition of such
>> core
>> >> API in the spec so the faster we can design a great API, the more
>> chances
>> >> there is to see it standardized.
>>
>> >>
>> >>
>> >> Regards,
>> >>
>> >> ~ Simon
>> >>
>> >> On Mon, Dec 8, 2008 at 4:22 AM, Gerhard Petracek
>> >> <[EMAIL PROTECTED]
>>
>> <mailto:[EMAIL PROTECTED]>> wrote:
>> >>
>> >> 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 <[EMAIL PROTECTED]
>> >> <mailto:[EMAIL PROTECTED]>>
>>
>> >>
>> >> 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
>>
>> >> /<[EMAIL PROTECTED]
>> >> <mailto:[EMAIL PROTECTED]>>/* wrote:
>>
>> >>
>> >> From: Gerhard Petracek
>> <[EMAIL PROTECTED]
>> >> <mailto:[EMAIL PROTECTED]>>
>>
>> >> Subject: Re: [Skinning] Independent skinning myfaces
>> >> subproject
>> >> To: "MyFaces Development"
>> <[email protected]
>>
>> >> <mailto:[email protected]>>
>> >> 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 <[EMAIL PROTECTED]
>> >> <mailto:[EMAIL PROTECTED]>>
>>
>> >>
>> >> 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
>> >> <[EMAIL PROTECTED]
>> >> <mailto:[EMAIL PROTECTED]>> 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
>> <[EMAIL PROTECTED]
>> >> <mailto:[EMAIL PROTECTED]>>
>>
>> >>
>> >> 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 <http://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
>>
>> >> <[EMAIL PROTECTED]
>> >>
>> <mailto:[EMAIL PROTECTED]>>
>> 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 nightma
>>
>> >
>> > ...
>> >
>> > [Message
>> clipped]
>>
>>
>>
>> --
>> Matthias Wessendorf
>>
>> blog: http://matthiaswessendorf.wordpress.com/
>> sessions: http://www.slideshare.net/mwessendorf
>>
>> twitter: http://twitter.com/mwessendorf
>>
>
>
>
> --
>
> http://www.irian.at
>
> Your JSF powerhouse -
> JSF Consulting, Development and
> Courses in English and German
>
> Professional Support for Apache MyFaces
>
--
Matthias Wessendorf
blog: http://matthiaswessendorf.wordpress.com/
sessions: http://www.slideshare.net/mwessendorf
twitter: http://twitter.com/mwessendorf