]> git.argeo.org Git - lgpl/argeo-commons.git/blob - argeo/cms/script/Theme.java
Prepare next development cycle
[lgpl/argeo-commons.git] / 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.RWT;
22 import org.eclipse.rap.rwt.application.Application;
23 import org.eclipse.rap.rwt.service.ResourceLoader;
24 import org.osgi.framework.Bundle;
25 import org.osgi.framework.BundleContext;
26
27 public class Theme {
28 private final static Log log = LogFactory.getLog(Theme.class);
29
30 private String themeId;
31 private Map<String, ResourceLoader> css = new HashMap<>();
32 private Map<String, ResourceLoader> resources = new HashMap<>();
33
34 private String headerCss;
35 private List<String> fonts = new ArrayList<>();
36
37 private String basePath;
38 private String cssPath;
39
40 public Theme(BundleContext bundleContext) {
41 this(bundleContext, null);
42 }
43
44 public Theme(BundleContext bundleContext, String symbolicName) {
45 Bundle themeBundle;
46 if (symbolicName == null) {
47 themeBundle = bundleContext.getBundle();
48 // basePath = "/theme/";
49 // cssPath = basePath;
50 } else {
51 themeBundle = ThemeUtils.findThemeBundle(bundleContext, symbolicName);
52 }
53 basePath = "/";
54 cssPath = "/rap/";
55 this.themeId = RWT.DEFAULT_THEME_ID;
56 addStyleSheets(themeBundle, new BundleResourceLoader(themeBundle));
57 BundleResourceLoader themeBRL = new BundleResourceLoader(themeBundle);
58 addResources(themeBRL, "*.png");
59 addResources(themeBRL, "*.gif");
60 addResources(themeBRL, "*.jpg");
61 addResources(themeBRL, "*.jpeg");
62 addResources(themeBRL, "*.svg");
63 addResources(themeBRL, "*.ico");
64
65 // fonts
66 URL fontsUrl = themeBundle.getEntry(basePath + "fonts.txt");
67 if (fontsUrl != null) {
68 loadFontsUrl(fontsUrl);
69 }
70
71 // common CSS header (plain CSS)
72 URL headerCssUrl = themeBundle.getEntry(basePath + "header.css");
73 if (headerCssUrl != null) {
74 try (BufferedReader buffer = new BufferedReader(new InputStreamReader(headerCssUrl.openStream(), UTF_8))) {
75 headerCss = buffer.lines().collect(Collectors.joining("\n"));
76 } catch (IOException e) {
77 throw new CmsException("Cannot read " + headerCssUrl, e);
78 }
79 }
80
81 }
82
83 public void apply(Application application) {
84 for (String name : resources.keySet()) {
85 application.addResource(name, resources.get(name));
86 if (log.isDebugEnabled())
87 log.debug("Added resource " + name);
88 }
89 for (String name : css.keySet()) {
90 application.addStyleSheet(themeId, name, css.get(name));
91 if (log.isDebugEnabled())
92 log.debug("Added RAP CSS " + name);
93 }
94 }
95
96 public String getAdditionalHeaders() {
97 StringBuilder sb = new StringBuilder();
98 if (headerCss != null) {
99 sb.append("<style type='text/css'>\n");
100 sb.append(headerCss);
101 sb.append("\n</style>\n");
102 }
103 for (String link : fonts) {
104 sb.append("<link rel='stylesheet' href='");
105 sb.append(link);
106 sb.append("'/>\n");
107 }
108 if (sb.length() == 0)
109 return null;
110 else
111 return sb.toString();
112 }
113
114 void addStyleSheets(Bundle themeBundle, ResourceLoader ssRL) {
115 Enumeration<URL> themeResources = themeBundle.findEntries(cssPath, "*.css", true);
116 if (themeResources == null)
117 return;
118 while (themeResources.hasMoreElements()) {
119 String resource = themeResources.nextElement().getPath();
120 // remove first '/' so that RWT registers it
121 resource = resource.substring(1);
122 if (!resource.endsWith("/")) {
123 if (css.containsKey(resource))
124 log.warn("Overriding " + resource + " from " + themeBundle.getSymbolicName());
125 css.put(resource, ssRL);
126 }
127
128 }
129
130 }
131
132 void loadFontsUrl(URL url) {
133 try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream(), UTF_8))) {
134 String line = null;
135 while ((line = in.readLine()) != null) {
136 line = line.trim();
137 if (!line.equals("") && !line.startsWith("#")) {
138 fonts.add(line);
139 }
140 }
141 } catch (IOException e) {
142 throw new CmsException("Cannot load URL " + url, e);
143 }
144 }
145
146 void addResources(BundleResourceLoader themeBRL, String pattern) {
147 Bundle themeBundle = themeBRL.getBundle();
148 Enumeration<URL> themeResources = themeBundle.findEntries(basePath, pattern, true);
149 if (themeResources == null)
150 return;
151 while (themeResources.hasMoreElements()) {
152 String resource = themeResources.nextElement().getPath();
153 // remove first '/' so that RWT registers it
154 resource = resource.substring(1);
155 if (!resource.endsWith("/")) {
156 if (resources.containsKey(resource))
157 log.warn("Overriding " + resource + " from " + themeBundle.getSymbolicName());
158 resources.put(resource, themeBRL);
159 }
160
161 }
162
163 }
164
165 public String getThemeId() {
166 return themeId;
167 }
168
169 public void setThemeId(String themeId) {
170 this.themeId = themeId;
171 }
172
173 public String getBasePath() {
174 return basePath;
175 }
176
177 public void setBasePath(String basePath) {
178 this.basePath = basePath;
179 }
180
181 public String getCssPath() {
182 return cssPath;
183 }
184
185 public void setCssPath(String cssPath) {
186 this.cssPath = cssPath;
187 }
188
189 }