1
2
3
4
5
6
7
8 package org.vaadin.openesignforms.ckeditor.widgetset.client.ui;
9
10 import java.util.HashMap;
11 import java.util.LinkedList;
12 import java.util.Set;
13
14 import com.google.gwt.core.client.Scheduler;
15 import com.google.gwt.core.client.Scheduler.ScheduledCommand;
16 import com.google.gwt.dom.client.DivElement;
17 import com.google.gwt.dom.client.Document;
18 import com.google.gwt.dom.client.Style.Overflow;
19 import com.google.gwt.dom.client.Style.Visibility;
20 import com.google.gwt.user.client.ui.Focusable;
21 import com.google.gwt.user.client.ui.Widget;
22 import com.vaadin.client.ApplicationConnection;
23 import com.vaadin.client.LayoutManager;
24 import com.vaadin.client.Paintable;
25 import com.vaadin.client.UIDL;
26 import com.vaadin.client.VConsole;
27 import com.vaadin.client.ui.layout.ElementResizeEvent;
28 import com.vaadin.client.ui.layout.ElementResizeListener;
29 import com.vaadin.shared.EventId;
30
31
32
33
34
35 public class VCKEditorTextField extends Widget implements Paintable, CKEditorService.CKEditorListener, Focusable {
36
37
38 public static final String CLASSNAME = "v-ckeditortextfield";
39
40 public static final String ATTR_FOCUS = "focus";
41 public static final String ATTR_IMMEDIATE = "immediate";
42 public static final String ATTR_READONLY = "readonly";
43 public static final String ATTR_VIEW_WITHOUT_EDITOR = "viewWithoutEditor";
44 public static final String ATTR_INPAGECONFIG = "inPageConfig";
45 public static final String ATTR_PROTECTED_SOURCE = "protectedSource";
46 public static final String ATTR_WRITERRULES_TAGNAME = "writerRules.tagName";
47 public static final String ATTR_WRITERRULES_JSRULE = "writerRules.jsRule";
48 public static final String ATTR_WRITER_INDENTATIONCHARS = "writerIndentationChars";
49 public static final String ATTR_INSERT_HTML = "insert_html";
50 public static final String ATTR_INSERT_TEXT = "insert_text";
51 public static final String ATTR_PROTECTED_BODY = "protected_body";
52 public static final String VAR_TEXT = "text";
53 public static final String VAR_VERSION = "version";
54
55 private static String ckeditorVersion;
56
57
58 protected String paintableId;
59
60
61 protected ApplicationConnection clientToServer;
62
63 private String dataBeforeEdit = null;
64
65 private boolean immediate;
66 private boolean readOnly;
67 private boolean viewWithoutEditor;
68 private boolean protectedBody;
69
70 private CKEditor ckEditor = null;
71 private boolean ckEditorIsReady = false;
72 private boolean resizeListenerInPlace = false;
73
74 private LinkedList<String> protectedSourceList = null;
75 private HashMap<String,String> writerRules = null;
76 private String writerIndentationChars = null;
77
78 private int tabIndex;
79 private boolean setFocusAfterReady;
80 private boolean setTabIndexAfterReady;
81
82
83
84
85
86 public VCKEditorTextField() {
87
88
89 DivElement rootDiv = Document.get().createDivElement();
90 rootDiv.getStyle().setOverflow(Overflow.HIDDEN);
91 rootDiv.getStyle().setVisibility(Visibility.VISIBLE);
92 setElement(rootDiv);
93
94
95
96 setStyleName(CLASSNAME);
97 }
98
99
100
101
102 @Override
103 public void updateFromUIDL(UIDL uidl, ApplicationConnection client) {
104 clientToServer = client;
105 paintableId = uidl.getId();
106 boolean needsDataUpdate = false;
107 boolean needsProtectedBodyUpdate = false;
108 boolean readOnlyModeChanged = false;
109
110
111
112
113
114 if ( clientToServer.updateComponent(this, uidl, true) ) {
115 return;
116 }
117
118 if ( ! resizeListenerInPlace ) {
119 LayoutManager.get(client).addElementResizeListener(getElement(), new ElementResizeListener() {
120
121 @Override
122 public void onElementResize(ElementResizeEvent e) {
123 doResize();
124 }
125
126 });
127 resizeListenerInPlace = true;
128 }
129
130 if ( uidl.hasAttribute(ATTR_IMMEDIATE) ) {
131 immediate = uidl.getBooleanAttribute(ATTR_IMMEDIATE);
132 }
133 if ( uidl.hasAttribute(ATTR_READONLY) ) {
134 boolean newReadOnly = uidl.getBooleanAttribute(ATTR_READONLY);
135 readOnlyModeChanged = newReadOnly != readOnly;
136 readOnly = newReadOnly;
137 }
138 if ( uidl.hasAttribute(ATTR_VIEW_WITHOUT_EDITOR) ) {
139 viewWithoutEditor = uidl.getBooleanAttribute(ATTR_VIEW_WITHOUT_EDITOR);
140 }
141 if ( uidl.hasAttribute(ATTR_PROTECTED_BODY) ) {
142 boolean state = uidl.getBooleanAttribute(ATTR_PROTECTED_BODY);
143 if (protectedBody != state) {
144 protectedBody = state ;
145 needsProtectedBodyUpdate = true;
146 }
147 }
148 if ( uidl.hasVariable(VAR_TEXT) ) {
149 String data = uidl.getStringVariable(VAR_TEXT);
150 if ( ckEditor != null )
151 dataBeforeEdit = ckEditor.getData();
152 needsDataUpdate = ! data.equals(dataBeforeEdit);
153 dataBeforeEdit = data;
154 }
155
156
157 if ( ! paintableId.equals(getElement().getId()) ) {
158 getElement().setId(paintableId);
159 }
160
161 if ( viewWithoutEditor ) {
162 if ( ckEditor != null ) {
163
164 if ( ! needsDataUpdate ) {
165 dataBeforeEdit = ckEditor.getData();
166 }
167 ckEditor.destroy(true);
168 ckEditorIsReady = false;
169 ckEditor = null;
170 }
171 getElement().setInnerHTML(dataBeforeEdit);
172 }
173 else if ( ckEditor == null ) {
174 getElement().setInnerHTML("");
175
176 final String inPageConfig = uidl.hasAttribute(ATTR_INPAGECONFIG) ? uidl.getStringAttribute(ATTR_INPAGECONFIG) : null;
177
178 writerIndentationChars = uidl.hasAttribute(ATTR_WRITER_INDENTATIONCHARS) ? uidl.getStringAttribute(ATTR_WRITER_INDENTATIONCHARS) : null;
179
180 if ( uidl.hasAttribute(ATTR_FOCUS) ) {
181 setFocus(uidl.getBooleanAttribute(ATTR_FOCUS));
182 }
183
184
185 int i = 0;
186 while( true ) {
187 if ( ! uidl.hasAttribute(ATTR_WRITERRULES_TAGNAME+i) ) {
188 break;
189 }
190
191 String tagName = uidl.getStringAttribute(ATTR_WRITERRULES_TAGNAME+i);
192 String jsRule = uidl.getStringAttribute(ATTR_WRITERRULES_JSRULE+i);
193 if ( writerRules == null ) {
194 writerRules = new HashMap<String,String>();
195 }
196 writerRules.put(tagName, jsRule);
197 ++i;
198 }
199
200
201 i = 0;
202 while( true ) {
203 if ( ! uidl.hasAttribute(ATTR_PROTECTED_SOURCE+i) ) {
204 break;
205 }
206
207 String regex = uidl.getStringAttribute(ATTR_PROTECTED_SOURCE+i);
208 if ( protectedSourceList == null ) {
209 protectedSourceList = new LinkedList<String>();
210 }
211 protectedSourceList.add(regex);
212 ++i;
213 }
214
215 ScheduledCommand scE = new ScheduledCommand() {
216 @Override
217 public void execute() {
218 ckEditor = (CKEditor)CKEditorService.loadEditor(paintableId,
219 VCKEditorTextField.this,
220 inPageConfig,
221 VCKEditorTextField.super.getOffsetWidth(),
222 VCKEditorTextField.super.getOffsetHeight());
223
224 }
225 };
226
227 CKEditorService.loadLibrary(scE);
228
229
230 } else if ( ckEditorIsReady ) {
231
232 if ( readOnlyModeChanged ) {
233 ckEditor.setReadOnly(readOnly);
234 }
235
236 if ( needsDataUpdate ) {
237 ckEditor.setData(dataBeforeEdit);
238 }
239
240 if ( needsProtectedBodyUpdate ) {
241 ckEditor.protectBody(protectedBody);
242 }
243
244 if (uidl.hasAttribute(ATTR_INSERT_HTML)) {
245 ckEditor.insertHtml(uidl.getStringAttribute(ATTR_INSERT_HTML));
246 }
247
248 if (uidl.hasAttribute(ATTR_INSERT_TEXT)) {
249 ckEditor.insertText(uidl.getStringAttribute(ATTR_INSERT_TEXT));
250 }
251
252 if ( uidl.hasAttribute(ATTR_FOCUS) ) {
253 setFocus(uidl.getBooleanAttribute(ATTR_FOCUS));
254 }
255 }
256
257 }
258
259
260 @Override
261 public void onSave() {
262 if ( ckEditorIsReady && ! readOnly ) {
263
264 String data = ckEditor.getData();
265 if ( ! data.equals(dataBeforeEdit) ) {
266 clientToServer.updateVariable(paintableId, VAR_TEXT, data, false);
267 dataBeforeEdit = data;
268 }
269 clientToServer.sendPendingVariableChanges();
270 }
271 }
272
273
274 @Override
275 public void onBlur() {
276 if ( ckEditorIsReady ) {
277 boolean sendToServer = false;
278
279 if ( clientToServer.hasEventListeners(this, EventId.BLUR) ) {
280 sendToServer = true;
281 clientToServer.updateVariable(paintableId, EventId.BLUR, "", false);
282 }
283
284
285
286 if ( ! readOnly ) {
287 String data = ckEditor.getData();
288 if ( ! data.equals(dataBeforeEdit) ) {
289 clientToServer.updateVariable(paintableId, VAR_TEXT, data, false);
290 sendToServer = true;
291 dataBeforeEdit = data;
292 }
293 }
294
295 if (sendToServer) {
296 clientToServer.sendPendingVariableChanges();
297 }
298 }
299 }
300
301
302 @Override
303 public void onFocus() {
304 if ( ckEditorIsReady ) {
305 if ( clientToServer.hasEventListeners(this, EventId.FOCUS) ) {
306 clientToServer.updateVariable(paintableId, EventId.FOCUS, "", true);
307 }
308 }
309 }
310
311
312 @Override
313 public void onInstanceReady() {
314 ckEditor.instanceReady(this);
315
316 if ( writerRules != null ) {
317 Set<String> tagNameSet = writerRules.keySet();
318 for( String tagName : tagNameSet ) {
319 ckEditor.setWriterRules(tagName, writerRules.get(tagName));
320 }
321 writerRules = null;
322 }
323
324 if ( writerIndentationChars != null ) {
325 ckEditor.setWriterIndentationChars(writerIndentationChars);
326 writerIndentationChars = null;
327 }
328
329 if ( protectedSourceList != null ) {
330 for( String regex : protectedSourceList ) {
331 ckEditor.pushProtectedSource(regex);
332 }
333 protectedSourceList = null;
334 }
335
336 if ( dataBeforeEdit != null ) {
337 ckEditor.setData(dataBeforeEdit);
338 }
339
340 ckEditorIsReady = true;
341 ckEditor.setReadOnly(readOnly);
342
343 if (setFocusAfterReady) {
344 setFocus(true);
345 }
346
347 if ( setTabIndexAfterReady ) {
348 setTabIndex(tabIndex);
349 }
350
351 doResize();
352
353 if (protectedBody) {
354 ckEditor.protectBody(protectedBody);
355 }
356 ckeditorVersion = CKEditorService.version();
357 clientToServer.updateVariable(paintableId, VAR_VERSION, ckeditorVersion, true);
358 }
359
360 @Override
361 public void setWidth(String width) {
362 super.setWidth(width);
363 doResize();
364 }
365
366 @Override
367 public void setHeight(String height) {
368 super.setHeight(height);
369 doResize();
370 }
371
372 protected void doResize() {
373 if (ckEditorIsReady) {
374 Scheduler.get().scheduleDeferred(new ScheduledCommand() {
375 @Override
376 public void execute() {
377 ckEditor.resize(VCKEditorTextField.super.getOffsetWidth(), VCKEditorTextField.super.getOffsetHeight());
378 }
379 });
380 }
381 }
382
383 @Override
384 protected void onUnload() {
385 if ( ckEditor != null ) {
386 ckEditor.destroy();
387 ckEditor = null;
388 }
389 ckEditorIsReady = false;
390 }
391
392 @Override
393 public void onChange() {
394 if ( ckEditor != null && ! readOnly ) {
395 String data = ckEditor.getData();
396 if ( ! data.equals(dataBeforeEdit) ) {
397 clientToServer.updateVariable(paintableId, VAR_TEXT, data, immediate);
398 dataBeforeEdit = data;
399 }
400 }
401 }
402
403 @Override
404 public void onModeChange(String mode) {
405 if ( ckEditor != null ) {
406 if ( ! readOnly ) {
407 String data = ckEditor.getData();
408 if ( ! data.equals(dataBeforeEdit) ) {
409 clientToServer.updateVariable(paintableId, VAR_TEXT, data, true);
410 dataBeforeEdit = data;
411 }
412 }
413
414 if ("wysiwyg".equals(mode)) {
415 ckEditor.protectBody(protectedBody);
416 }
417 }
418 }
419
420 @Override
421 public void onDataReady() {
422 if ( ckEditor != null ) {
423 ckEditor.protectBody(protectedBody);
424 }
425 }
426
427 @Override
428 public int getTabIndex() {
429 if (ckEditorIsReady) {
430 return ckEditor.getTabIndex();
431 } else {
432 return tabIndex;
433 }
434 }
435
436 @Override
437 public void setTabIndex(int tabIndex) {
438 if (ckEditorIsReady) {
439 ckEditor.setTabIndex(tabIndex);
440 } else {
441 setTabIndexAfterReady = true;
442 }
443 this.tabIndex = tabIndex;
444 }
445
446 @Override
447 public void setAccessKey(char arg0) {
448 return;
449 }
450
451 @Override
452 public void setFocus(boolean arg0) {
453 if (arg0) {
454 if (ckEditorIsReady)
455 ckEditor.focus();
456 else
457 setFocusAfterReady = true;
458 } else {
459 setFocusAfterReady = false;
460 }
461 }
462
463 }