]> git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms.ui/src/org/argeo/cms/script/Theme.java
51fc65ddab7f6d37cf1327443690d488dab2200c
[lgpl/argeo-commons.git] / org.argeo.cms.ui / src / org / argeo / cms / script / Theme.java
1 package org.argeo.cms.script;
2
3 import static java.nio.charset.StandardCharsets.UTF_8;
4
5 import java.io.BufferedReader;
6 import java.io.IOException;
7 import java.io.InputStreamReader;
8 import java.net.URL;
9 import java.util.ArrayList;
10 import java.util.Enumeration;
11 import java.util.HashMap;
12 import java.util.List;
13 import java.util.Map;
14 import java.util.stream.Collectors;
15
16 import org.apache.commons.logging.Log;
17 import org.apache.commons.logging.LogFactory;
18 import org.argeo.cms.CmsException;
19 import org.argeo.cms.util.BundleResourceLoader;
20 import org.argeo.cms.util.ThemeUtils;
21 import org.eclipse.rap.rwt.application.Application;
22 import org.eclipse.rap.rwt.service.ResourceLoader;
23 import org.osgi.framework.Bundle;
24 import org.osgi.framework.BundleContext;
25
26 public class Theme {
27 private final static Log log = LogFactory.getLog(Theme.class);
28
29 private String themeId;
30 private Map<String, ResourceLoader> css = new HashMap<>();
31 private Map<String, ResourceLoader> resources = new HashMap<>();
32
33 private String headerCss;
34 private List<String> fonts = new ArrayList<>();
35
36 public Theme(BundleContext bundleContext, String symbolicName) {
37 this.themeId = symbolicName;
38 Bundle themeBundle = ThemeUtils.findThemeBundle(bundleContext, symbolicName);
39 addStyleSheets(themeBundle, new BundleResourceLoader(themeBundle));
40 BundleResourceLoader themeBRL = new BundleResourceLoader(themeBundle);
41 addResources(themeBRL, "*.png");
42 addResources(themeBRL, "*.gif");
43 addResources(themeBRL, "*.jpg");
44 addResources(themeBRL, "*.jpeg");
45 addResources(themeBRL, "*.svg");
46 addResources(themeBRL, "*.ico");
47
48 // fonts
49 URL fontsUrl = themeBundle.getEntry("fonts.txt");
50 if (fontsUrl != null) {
51 loadFontsUrl(fontsUrl);
52 }
53
54 // common CSS header (plain CSS)
55 URL headerCssUrl = themeBundle.getEntry("header.css");
56 if (headerCssUrl != null) {
57 try (BufferedReader buffer = new BufferedReader(new InputStreamReader(headerCssUrl.openStream(), UTF_8))) {
58 headerCss = buffer.lines().collect(Collectors.joining("\n"));
59 } catch (IOException e) {
60 throw new CmsException("Cannot read " + headerCssUrl, e);
61 }
62 }
63
64 }
65
66 public void apply(Application application) {
67 for (String name : resources.keySet()) {
68 application.addResource(name, resources.get(name));
69 }
70 for (String name : css.keySet()) {
71 application.addStyleSheet(themeId, name, css.get(name));
72 }
73 }
74
75 public String getAdditionalHeaders() {
76 StringBuilder sb = new StringBuilder();
77 if (headerCss != null) {
78 sb.append("<style type='text/css'>\n");
79 sb.append(headerCss);
80 sb.append("\n</style>\n");
81 }
82 for (String link : fonts) {
83 sb.append("<link rel='stylesheet' href='");
84 sb.append(link);
85 sb.append("'/>\n");
86 }
87 if (sb.length() == 0)
88 return null;
89 else
90 return sb.toString();
91 }
92
93 void addStyleSheets(Bundle themeBundle, ResourceLoader ssRL) {
94 Enumeration<URL> themeResources = themeBundle.findEntries("/rap", "*.css", true);
95 if (themeResources == null)
96 return;
97 while (themeResources.hasMoreElements()) {
98 String resource = themeResources.nextElement().getPath();
99 // remove first '/' so that RWT registers it
100 resource = resource.substring(1);
101 if (!resource.endsWith("/")) {
102 if (css.containsKey(resource))
103 log.warn("Overriding " + resource + " from " + themeBundle.getSymbolicName());
104 css.put(resource, ssRL);
105 }
106
107 }
108
109 }
110
111 void loadFontsUrl(URL url) {
112 try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8))) {
113 String line = null;
114 while ((line = in.readLine()) != null) {
115 line = line.trim();
116 if (!line.equals("") && !line.startsWith("#")) {
117 fonts.add(line);
118 }
119 }
120 } catch (IOException e) {
121 throw new CmsException("Cannot load URL " + url, e);
122 }
123 }
124
125 void addResources(BundleResourceLoader themeBRL, String pattern) {
126 Bundle themeBundle = themeBRL.getBundle();
127 Enumeration<URL> themeResources = themeBundle.findEntries("/", pattern, true);
128 if (themeResources == null)
129 return;
130 while (themeResources.hasMoreElements()) {
131 String resource = themeResources.nextElement().getPath();
132 // remove first '/' so that RWT registers it
133 resource = resource.substring(1);
134 if (!resource.endsWith("/")) {
135 if (resources.containsKey(resource))
136 log.warn("Overriding " + resource + " from " + themeBundle.getSymbolicName());
137 resources.put(resource, themeBRL);
138 }
139
140 }
141
142 }
143
144 public String getThemeId() {
145 return themeId;
146 }
147
148 }