1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34 package info.magnolia.poc;
35
36 import static com.vaadin.server.Sizeable.Unit.PIXELS;
37
38 import info.magnolia.objectfactory.Components;
39 import info.magnolia.ui.field.RichTextFieldDefinition;
40 import info.magnolia.ui.field.factory.RichTextFieldFactory;
41 import info.magnolia.ui.vaadin.ckeditor.MagnoliaCKEditorTextField;
42
43 import java.beans.PropertyDescriptor;
44 import java.util.Arrays;
45 import java.util.Comparator;
46 import java.util.HashMap;
47 import java.util.List;
48 import java.util.Map;
49 import java.util.Optional;
50 import java.util.stream.Collectors;
51
52 import javax.servlet.annotation.WebServlet;
53
54 import org.apache.commons.beanutils.PropertyUtils;
55 import org.apache.commons.lang3.ClassUtils;
56
57 import com.vaadin.annotations.Theme;
58 import com.vaadin.annotations.Title;
59 import com.vaadin.annotations.VaadinServletConfiguration;
60 import com.vaadin.annotations.Widgetset;
61 import com.vaadin.data.Binder;
62 import com.vaadin.data.converter.StringToLongConverter;
63 import com.vaadin.server.VaadinRequest;
64 import com.vaadin.server.VaadinServlet;
65 import com.vaadin.shared.ui.ContentMode;
66 import com.vaadin.ui.AbstractField;
67 import com.vaadin.ui.Button;
68 import com.vaadin.ui.CheckBox;
69 import com.vaadin.ui.Component;
70 import com.vaadin.ui.CssLayout;
71 import com.vaadin.ui.FormLayout;
72 import com.vaadin.ui.Label;
73 import com.vaadin.ui.TextField;
74 import com.vaadin.ui.UI;
75
76
77
78
79 @Theme("poctheme")
80 @Title("Magnolia 6 Resurface - CKEditor")
81 @Widgetset("info.magnolia.poc.Widgetset")
82 public class CKEditorUI extends UI {
83 private static final Map<String, String> PROPERTY_INPUTPROMPTS = new HashMap<String, String>() {
84 {
85 put("colors", "e.g. blue,green,da444f");
86 put("fonts", "e.g. Helvetica;Times;Menlo");
87 put("fontSizes", "e.g. 10px;0.8em;1em;1.4em");
88 put("configJsFile", "e.g. /.resources/ckeditor/config-magnolia.js");
89 }
90 };
91
92 private Binder<RichTextFieldDefinition> binder;
93 private MagnoliaCKEditorTextField richTextField;
94 private FormLayout form;
95
96 @Override
97 protected void init(VaadinRequest request) {
98 form = new FormLayout();
99 form.setMargin(true);
100 createAndBindFields(form);
101
102 form.addComponent(new Label("<b>Change settings above and click on 'Open CKEditor' in order to see them applied. Opening a link to Pages or DAM won't work here ¯\\\\_(ツ)_/¯</b>", ContentMode.HTML));
103
104 final Button submit = new Button("Open CKEditor", event -> {
105 Optional.ofNullable(richTextField).ifPresent(form::removeComponent);
106
107 richTextField = (MagnoliaCKEditorTextField) new RichTextFieldFactory(binder.getBean(), null, null, null, null).createField();
108 richTextField.setCaption("Rich text field");
109 richTextField.setWidth(682, PIXELS);
110 richTextField.setValue("Die sinnliche Gewißheit oder das Diese und das Meinen" +
111 "<p>Das Wissen, welches zuerst oder unmittelbar unser Gegenstand ist, kann kein anderes sein als dasjenige, welches selbst unmittelbares Wissen, Wissen des Unmittelbaren oder Seienden ist. " +
112 "Wir haben uns ebenso unmittelbar oder aufnehmend zu verhalten, also nichts an ihm, wie es sich darbietet, zu verändern und von dem Auffassen das Begreifen abzuhalten. " +
113 "<p>(Giovanni Trapattoni)");
114 form.addComponent(richTextField);
115 });
116 form.addComponent(submit);
117 setContent(form);
118 }
119
120
121 private void createAndBindFields(FormLayout form) {
122
123 List<PropertyDescriptor> properties = Arrays.stream(PropertyUtils.getPropertyDescriptors(RichTextFieldDefinition.class))
124 .filter(p -> !(p.getPropertyType().isAssignableFrom(Class.class)))
125 .filter(p -> p.getWriteMethod().getDeclaringClass() == RichTextFieldDefinition.class)
126 .sorted(new RichTextFieldDefinitionPropertiesComparator())
127 .collect(Collectors.toList());
128
129
130 binder = new Binder(RichTextFieldDefinition.class);
131 binder.setBean(new RichTextFieldDefinition());
132
133
134 properties.forEach(property -> {
135 AbstractField<?> field = createField(property.getPropertyType());
136
137 Binder.BindingBuilder builder = binder.forField(field);
138 if (property.getName().equalsIgnoreCase("height")) {
139 ((TextField) field).setPlaceholder("300");
140 builder.withConverter(new StringToLongConverter((String) field.getValue()));
141 field.setWidth(100, PIXELS);
142 }
143 if (PROPERTY_INPUTPROMPTS.containsKey(property.getName())) {
144 ((TextField) field).setPlaceholder(PROPERTY_INPUTPROMPTS.get(property.getName()));
145 }
146 builder.bind(property.getName());
147 if (field instanceof CheckBox) {
148
149
150 Component wrappedCheckbox = new CssLayout(field);
151 wrappedCheckbox.setCaption(property.getName());
152 form.addComponent(wrappedCheckbox);
153 } else {
154 field.setCaption(property.getName());
155 form.addComponent(field);
156 }
157 });
158 }
159
160
161
162
163 private static class RichTextFieldDefinitionPropertiesComparator implements Comparator<PropertyDescriptor> {
164 @Override
165 public int compare(PropertyDescriptor o1, PropertyDescriptor o2) {
166
167 if (o1.getName().equalsIgnoreCase("configJsFile")) {
168 return 1;
169 } else if (o2.getName().equalsIgnoreCase("configJsFile")) {
170 return -1;
171 }
172
173 Class<?> pt1 = ClassUtils.primitiveToWrapper(o1.getPropertyType());
174 Class<?> pt2 = ClassUtils.primitiveToWrapper(o2.getPropertyType());
175 if (pt1.equals(pt2)) {
176 return o1.getName().compareToIgnoreCase(o2.getName());
177 }
178
179 if (ClassUtils.isAssignable(o1.getPropertyType(), Boolean.class)) {
180 return -1;
181 } else if (ClassUtils.isAssignable(pt2, Boolean.class)) {
182 return 1;
183 }
184
185 if (ClassUtils.isAssignable(o1.getPropertyType(), Number.class)) {
186 return -1;
187 } else if (ClassUtils.isAssignable(pt2, Number.class)) {
188 return 1;
189 }
190 return 0;
191 }
192 }
193
194 private <T extends AbstractField> T createField(Class<?> fieldType) {
195 if (fieldType.isAssignableFrom(Boolean.class) || fieldType.getName().equals("boolean")) {
196 return (T) new CheckBox();
197 }
198 T field = (T) new TextField();
199 field.setWidth(682, PIXELS);
200 return field;
201 }
202
203 @WebServlet(value = "/ckeditor/*", asyncSupported = true)
204 @VaadinServletConfiguration(productionMode = false, ui = CKEditorUI.class)
205 public static class Servlet extends VaadinServlet {
206 }
207 }