Architecture

Parse and Apply

Pour appliquer un style à l'aide d'une feuille de style CSS, les 2 étapes suivants sont nécessaires :

Parse style sheet

Voici un schéma qui décrit le processus de parsing d'une feuille de style à l'aide du moteur CSS.

Le parsing de la feuille permet d'alimenter une instance w3c CSSStyleSheet qui est stockée en interne dans une instance w3c DocumentCSS de engine.

  • (1): appel de la méthode parseStyleSheet d'une instance CSS Engine avec le contenu «input{color:green}». L'appel de cette méthode permet d'alimenter une instance w3c CSSStyleSheet. Cette instance est ajoutée à la liste StyleSheetList de l'instance w3c DocumentCSS du CSS engine.
  • (2): le moteur CSS parse la feuille de style à l'aide de la méthode parseStyleSheet d'une instance org.akrogen.tkui.css.core.dom.parsers.CSSParser. Un parseur CSS fait appel à un parseur w3c SAC. Un parseur SAC fonctionne comme un parseur SAX. En effet le parseur SAC déclenche des évenements qui peuvent être interceptés à l'aide d'une implémentation de org.w3c.css.sac.DocumentHandler. Le parseur CSS renseigne le DocumentHandler à utiliser qui permet de récupérer une instance CSSStyleSheet.
  • (3): Le DocumentHandler SAC implémente :
    1. l'évenement startDocument (appelé au debut du parsing) qui à la signature suivante : public void startDocument(InputSource source) throws CSSException Dans cette méthode une instance CSSStyleSheet est créer.
    2. L'évenement startSelector (appelé lorsque le selector input est trouvé) qui à la signature : public void startSelector(SelectorList selectors) throws CSSException Dans cette méthode une instance CSSStyleRule est instancié et ajouté au CSSStyleSheet créer dans la méthode startDocument. Une instance CSSStyleDeclaration est créée et ajouté à l'instance CSSStyleRule.
    3. l'évenement property (appelé à chaque propriété CSS parsée) qui à la signature suivante : public void property(String s, LexicalUnit lexicalunit, boolean flag) throws CSSException; Dans la feuille de style parsée, le paramètre s vaut color. C'est le nom de la propriété. LexicalUnit est la valeur SAC parsée. lexicalUnit.getStringValue() retourne red.
  • (4): Une instance w3c CSSValue est créé à partir du LexicalUnit.
  • (5): L'instance CSSValue est ajouté au style CSSStyleDeclaration créé dans l'évenement startSelector.

A cette étape le moteur CSS à une instance org.w3c.dom.css.DocumentCSS qui contient l'instance CSSStyleSheet mise à jour. L'arbre CSStyleSheet construit suit la spécification w3c.

Ici on peut remarquer que les valeurs LexicalUnit SAC sont transformés en CSSValue, qui seront transformés à l'étape d'application des styles en vrai objet du renderer (Swing, SWT) (comme java.awt.Color, Font...). Pourquoi ne pas convertir directement les valeurs LexicalUnit en objets java.awt.Color, Font...? La première réponse est de respecter la norme w3c qui propose de travailler avec des valeurs CSSValue. La deuxième réponse est que les styles doivent etre caclculés et pour certaine ressources comme les Font, il n'est pas possible de calcules à l'avance la Font. Autrement dit si on a une feuille de style comme ceci :

input {
   font-size:10;
}
input[type=checkbox] {
   font-family:Serif;
}
les input (avec type=checkbox (en Swing JCheckBox)) aurront un java.awt.Font avec family=Serif et une size=10. Les autres input (JTextField,....) aurront un java.awt.Font avec size=10. Le calcul du style s'effectue lors de l'application du style. Le code suivant récupère le DocumentCSS w3c du CSS engine et affiche toutes les propriétés CSS du CSSStyleSheet alimenté par le parseur SAC.
// Parse style sheet
CSSEngine engine = new CSSEngineImpl();
engine.parseStyleSheet(new StringReader("input{color:red}"));

// Get w3c DocumentCSS of CSS engine
DocumentCSS documentCSS = engine.getDocumentCSS();

// Loop for CSS Style sheet stored into w3c DocumentCSS
StyleSheetList styleSheetList = documentCSS.getStyleSheets();
for (int i = 0; i < styleSheetList.getLength(); i++) {
	CSSStyleSheet styleSheet = (CSSStyleSheet) styleSheetList.item(i);
	// Loop for CSS Rule list registered into current CSS Style sheet
	CSSRuleList ruleList = styleSheet.getCssRules();
	for (int j = 0; j < ruleList.getLength(); j++) {
		// Get style of CSSStyleRule
		CSSStyleRule rule = (CSSStyleRule) ruleList.item(j);
		CSSStyleDeclaration styleDeclaration = rule.getStyle();
		// Loop for CSS property o CSSStyleDeclaration.
		for (int k = 0; k < styleDeclaration.getLength(); k++) {
			String propertyName = styleDeclaration.item(k);
			CSSValue value = styleDeclaration
					.getPropertyCSSValue(propertyName);
			System.out.println("CSS property name=" + propertyName
					+ ", value=" + value);
		}
	}
}