BrightSide Workbench Full Report + Source Code
BannerComposer.java
Go to the documentation of this file.
1 /*
2  * TurrĂ³ i Cutiller Foundation. License notice.
3  * Copyright (C) 2018 Lluis TurrĂ³ Cutiller <http://www.turro.org/>
4  *
5  * This program is free software: you can redistribute it and/or modify
6  * it under the terms of the GNU Affero General Public License as published by
7  * the Free Software Foundation, either version 3 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU Affero General Public License for more details.
14  *
15  * You should have received a copy of the GNU Affero General Public License
16  * along with this program. If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 package org.turro.newsletter;
20 
21 import com.steadystate.css.parser.CSSOMParser;
22 import com.steadystate.css.parser.SACParserCSS3;
23 import java.io.File;
24 import java.io.IOException;
25 import java.io.StringReader;
26 import java.util.HashMap;
27 import java.util.logging.Level;
28 import java.util.logging.Logger;
29 import org.turro.string.Strings;
30 import org.jsoup.Jsoup;
31 import org.jsoup.nodes.Document;
32 import org.jsoup.nodes.Element;
33 import org.jsoup.select.Elements;
34 import org.turro.command.Command;
35 import org.turro.command.Context;
36 import org.turro.elephant.context.Application;
37 import org.turro.elephant.context.ElephantContext;
38 import org.turro.i18n.I_;
39 import org.turro.zkoss.dialog.SelectionDialog;
40 import org.turro.zkoss.text.RepositoryContent;
41 import org.turro.zkoss.text.RepositoryWalker;
42 import org.w3c.css.sac.InputSource;
43 import org.w3c.dom.css.CSSStyleDeclaration;
44 import org.zkoss.zk.ui.Executions;
45 import org.zkoss.zk.ui.IdSpace;
46 import org.zkoss.zk.ui.event.Event;
47 import org.zkoss.zk.ui.select.Selectors;
48 import org.zkoss.zk.ui.select.annotation.Listen;
49 import org.zkoss.zk.ui.select.annotation.Wire;
50 import org.zkoss.zkex.zul.Colorbox;
51 import org.zkoss.zul.Checkbox;
52 import org.zkoss.zul.Div;
53 import org.zkoss.zul.Html;
54 import org.zkoss.zul.Textbox;
55 
60 public class BannerComposer extends Div implements IdSpace {
61 
62  private final String entityPath;
63 
64  @Wire("#width") private Textbox width;
65  @Wire("#label") private Textbox label;
66  @Wire("#color") private Colorbox color;
67  @Wire("#bgColor") private Colorbox bgColor;
68  @Wire("#fontSize") private Textbox fontSize;
69  @Wire("#bold") private Checkbox bold;
70  @Wire("#italic") private Checkbox italic;
71  @Wire("#underline") private Checkbox underline;
72  @Wire("#banner") private Html html;
73 
74  @Listen("onChange = *; onSelect = *; onCheck = *")
75  public final void onChange(Event event) {
76  html.setContent(bannerString());
77  }
78 
79  @Listen("onClick = #selImage")
80  public void onSelectImage() {
81  RepositoryWalker repositories = new RepositoryWalker(null);
82  repositories.selectFolder("/_internal/files" + entityPath);
84  repositories.setReadOnlyRepository(Strings.isBlank(entityPath));
85  repositories.setNoTreeRepository(false);
86  SelectionDialog.showComponent(getPage(), I_.get("Repository"), repositories, "90%", "90%", new Command() {
87  @Override
88  public Object execute(Context context) {
89  File result = repositories.getResult();
90  if(result != null) {
91  imgSrc = ElephantContext.getRootWebPath() +
92  ElephantContext.getRelativePath(result.getAbsolutePath());
93  }
94  html.setContent(bannerString());
95  return null;
96  }
97  });
98  }
99 
100  @Listen("onClick = #delImage")
101  public void onDeleteImage() {
102  imgSrc = null;
103  html.setContent(bannerString());
104  }
105 
106  public BannerComposer(String htmlStr, String entityPath) {
107  HashMap args = new HashMap();
108  args.put("el_label", Application.getStringMap());
109  args.put("i_", I_.api());
110  args.put("i", I_.map());
111  args.put("k", I_.byKeyMap());
112  Executions.createComponents("/WEB-INF/_zul/bs/comps/editor/bannerComposer.zul", this, args);
113  Selectors.wireComponents(this, this, false);
114  Selectors.wireEventListeners(this, this);
115  this.entityPath = entityPath;
116  parseValues(htmlStr);
117  html.setContent(bannerString());
118  }
119 
120  public String getResult() {
121  return bannerString();
122  }
123 
124  /* HTML */
125 
126  private String imgSrc;
127 
128  private String bannerString() {
129  if(Strings.isBlank(label.getValue())) return "";
130 
131  StringBuilder sb = new StringBuilder();
132  sb.append("<table width=\"100%\" cellpadding=\"0\" cellspacing=\"0\" border=\"0\" style=\"width:100%;\">")
133  .append("<tr valign=\"middle\" style=\"vertical-align:middle;\">");
134  if(!Strings.isBlank(imgSrc)) {
135  sb.append("<td ");
136  if(!Strings.isBlank(width.getValue())) {
137  sb.append("width=\"")
138  .append(width.getValue())
139  .append("\" ");
140  }
141  sb.append("style=\"");
142  if(!Strings.isBlank(bgColor.getValue())) {
143  if(underline.isChecked()) {
144  sb.append("border-bottom-style:solid;border-bottom-width:3px;border-bottom-color:")
145  .append(bgColor.getValue())
146  .append(";");
147  } else {
148  sb.append("background-color:")
149  .append(bgColor.getValue())
150  .append(";");
151  }
152  }
153  if(!Strings.isBlank(width.getValue())) {
154  sb.append("width:")
155  .append(width.getValue())
156  .append(";");
157  }
158  sb.append("\"><img border=\"0\" style=\"");
159  if(!Strings.isBlank(width.getValue())) {
160  sb.append("width:")
161  .append(width.getValue())
162  .append(";");
163  }
164  sb.append("\" src=\"")
165  .append(imgSrc)
166  .append("\"/></td>");
167  }
168  if(!Strings.isBlank(label.getValue())) {
169  sb.append("<td style=\"padding-left:10px;");
170  if(!Strings.isBlank(fontSize.getValue())) {
171  sb.append("font-size:")
172  .append(fontSize.getValue())
173  .append(";");
174  }
175  if(bold.isChecked()) {
176  sb.append("font-weight:bold;");
177  } else {
178  sb.append("font-weight:normal;");
179  }
180  if(italic.isChecked()) {
181  sb.append("font-style:italic;");
182  } else {
183  sb.append("font-style:normal;");
184  }
185  if(!Strings.isBlank(color.getValue())) {
186  sb.append("color:")
187  .append(color.getValue())
188  .append(";");
189  }
190  if(!Strings.isBlank(bgColor.getValue())) {
191  if(underline.isChecked()) {
192  sb.append("border-bottom-style:solid;border-bottom-width:3px;border-bottom-color:")
193  .append(bgColor.getValue())
194  .append(";");
195  } else {
196  sb.append("background-color:")
197  .append(bgColor.getValue())
198  .append(";");
199  }
200  }
201  sb.append("\">")
202  .append(label.getValue())
203  .append("</td>");
204  }
205  sb.append("</tr></table>")
206  .append(divider(10));
207 
208  return sb.toString();
209  }
210 
211  private String divider(int height) {
212  return "<div width=\"100%\" style=\"width:100%;height:" + height + "px;\">&nbsp;</div>";
213  }
214 
215  private void parseValues(String html) {
216  if(Strings.isBlank(html)) return;
217  Document document = Jsoup.parse(html);
218  Elements images = document.getElementsByTag("img");
219  if(!images.isEmpty()) {
220  Element image = images.first();
221  CSSStyleDeclaration style = parseStyle(image);
222  if(style != null) {
223  width.setValue(style.getPropertyValue("width"));
224  }
225  imgSrc = image.attr("src");
226  }
227  Elements tds = document.getElementsByTag("td");
228  if(!tds.isEmpty()) {
229  Element td = tds.last();
230  CSSStyleDeclaration style = parseStyle(td);
231  if(style != null) {
232  fontSize.setValue(style.getPropertyValue("font-size"));
233  bold.setChecked("bold".equals(style.getPropertyValue("font-weight")));
234  italic.setChecked("italic".equals(style.getPropertyValue("font-style")));
235  if(!Strings.isBlank(style.getPropertyValue("color"))) {
236  color.setValue(convert(style.getPropertyValue("color")));
237  }
238  if("solid".equals(style.getPropertyValue("border-bottom-style"))) {
239  if(!Strings.isBlank(style.getPropertyValue("border-bottom-color"))) {
240  bgColor.setValue(convert(style.getPropertyValue("border-bottom-color")));
241  }
242  underline.setChecked(true);
243  } else {
244  if(!Strings.isBlank(style.getPropertyValue("background-color"))) {
245  bgColor.setValue(convert(style.getPropertyValue("background-color")));
246  }
247  underline.setChecked(false);
248  }
249  }
250  label.setValue(td.html());
251  }
252  }
253 
254  private CSSStyleDeclaration parseStyle(Element element) {
255  String style = element.attr("style");
256  if(!Strings.isBlank(style)) {
257  try {
258  InputSource source = new InputSource(new StringReader(style));
259  CSSOMParser parser = new CSSOMParser(new SACParserCSS3());
260  return parser.parseStyleDeclaration(source);
261  } catch (IOException ex) {
262  Logger.getLogger(BannerComposer.class.getName()).log(Level.SEVERE, ElephantContext.logMsg(null), ex);
263  }
264  }
265  return null;
266  }
267 
268  private String convert(String propertyValue) {
269  if(propertyValue.startsWith("rgb")) {
270  String colors[] = propertyValue.substring(4, propertyValue.length() - 1).split("\\s*,\\s*");
271  propertyValue = String.format("#%02x%02x%02x",
272  Integer.parseInt(colors[0]), Integer.parseInt(colors[1]), Integer.parseInt(colors[2]));
273  }
274  return propertyValue;
275  }
276 
277 }
static I18nByKey byKeyMap()
Definition: I_.java:91
static String get(String msg)
Definition: I_.java:41
static I18nApiWrapper api()
Definition: I_.java:65
static I18nMapWrapper map()
Definition: I_.java:69
final void onChange(Event event)
BannerComposer(String htmlStr, String entityPath)
static void showComponent(Page page, String title, Component component, String width, String height, final Command command)
void setNoTreeRepository(boolean noTreeRepository)
void setReadOnlyRepository(boolean readOnlyRepository)