marți, august 31, 2010

Multiple themes and skins

Este prima oara cand lucrez la o aplicatie Web care trebuie sa aiba mai multe look and feel-uri care pot fi schimbate in runtime (vom numi aceasta drept schimbarea temei aplicatie). Exista tehnologii web care permit schimbarea stilului (nu a a temei) in runtime – JSF, librarii de componente JS gen JQuery UI. Si in partea de clienti grei exista astfel de posibilitati: Swing LAF (o lista a lor), sau mai noul Eclipse RCP 4 – look and feel dat chiar prin CSS. Dar eu vreau sa schimb tot layout-ul aplicatiei cu toate resursele implicate – css, javascript, resurse gen imagini, bannere, etc.

Pentru mine definitiile pentru tema si skin arata mai mult in felul in care se definesc acestea in portlets (partal theme, portlet skin):
  • Tema – modificarile se produc la nivel de layout si stil (chiar daca stilul este dat de CSS si poate influenta foarte fin si layout-ul totusi o tema implica o schimbare dramatica a modului in care arata site-ul)
  • Skin – modificarile au loc la nivel de stil (a se vedea JQuery UI pentru exemplu)
Desigur notiunile de skin si theme sun folosite cu intelesuri diferite in tehnologii diferite. Un exemplu revelator pentru ce inseamna fiecare pentru mine este acest site cu teme pentru WordPress in care se poate face distinctia clara dintre cele doua. Intr-un fel tema poate fi modificata de catre administratorul site-ului deoarece implica modificari profunde in look and feel. Skin-ul poate fi modificat de user si pastrat de-a lungul sesiunii si dupa. Ambele schimbari trebuie sa se poata face in runtime – din panoul de administrare a aplicatiei.

Partea de prezentare pentru aplicatia in cauza este facuta cu Struts 2, Sitemesh (este valabil si pentru alt framework web gen Spring MVC sau alt layout framework gen Tiles). Deoarece tema implica modificari de layout in cazul temei concluzia la care am ajuns este: sa folosesc facilitatea asta de Struts 2 numita wildcards. Astfel applicationConfiguration* va pinta spre /WEB-INF/pages/admin/applicationConfiguration{1}.jsp.

In form o sa se foloseasca ceva de genul (theme va fi tinuta la nivel de applicatie – Application Context (Servlet context in servlets)): applicationConfiguration${theme}.html


Pentru fiecare tema se va crea un director in aplicatie sub un singur director parinte numit /themes. Structura unei teme ar arata ca aici cum e descrisa in Sitemesh.

  1. /decorators Directory containing all decorator files (e.g. main.jsp, printable.jsp).
  2. /includes Directory containing all files to be included into other files (e.g. header.jsp, footer.jsp, copyright.jsp).
  3. /images Directory containing all images (e.g. background.gif, logo.gif).
  4. /styles Directory containing all .CSS styles (e.g. ie4.css, ns4.css).
  5. /scripts Directory containing all scripts (JavaScript, VBScript files).

Vom avea cate un decorator de SiteMesh diferit pentru fiecare thema (care da layout-ul de baza pentru thema respectiva). Se refolosesc Action-urile de Struts pentru toate temele si in acest sens ele trebuie sa fie scrise o singura data si foarte bine definite - nu mai trebuie rescris nimic la nivelul lor in functie de tema - dar trebuie sa fie consistente pentru toate temele. Toate resursele grafice vor fi sub tema respectiva. Se vor duplica jsp-urile aplicatiei (se folosesc in fiecare resurse specifice temei) - dar pentru theme identice ca layout vor fi asemanatoare si deci se poate presupune ca vor putea fi refolosite.

Deci implementarea este dependenta de Struts 2 si de Sitemesh adica de tehnologiile folosite in aplicatie. Intrebarea este daca exista ceva mai generic (poate independent de framework-uri) sau mai bun. Din ce imi dau seama nu – doar la nivel de stil prin introducerea de CSS-uri diferite – care pot sa contina si mici chestiuni de layout dar nu diferente mari. Sunt curios cum s-ar putea face acest lucru la nivel de JSF – probabil entry point-ul ar fi la nivel de Facelets.

Anumite greutati in introducerea temelor multiple pentru o aplicatie apar in rescrierea de URL-uri (UrlRewrite), caching de pagini (OSCache) si securitate (ACEGI). O problema este introducerea unor variabile la nivel de aplicatie (numele temei, locatia temei in FileSystem) care trebuie folosite si repetate peste tot la nivel de JSP-uri.