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