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 = loadEditor(inPageConfig);
219 }
220 };
221
222 CKEditorService.loadLibrary(scE);
223
224
225 } else if ( ckEditorIsReady ) {
226
227 if ( readOnlyModeChanged ) {
228 ckEditor.setReadOnly(readOnly);
229 }
230
231 if ( needsDataUpdate ) {
232 ckEditor.setData(dataBeforeEdit);
233 }
234
235 if ( needsProtectedBodyUpdate ) {
236 ckEditor.protectBody(protectedBody);
237 }
238
239 if (uidl.hasAttribute(ATTR_INSERT_HTML)) {
240 ckEditor.insertHtml(uidl.getStringAttribute(ATTR_INSERT_HTML));
241 }
242
243 if (uidl.hasAttribute(ATTR_INSERT_TEXT)) {
244 ckEditor.insertText(uidl.getStringAttribute(ATTR_INSERT_TEXT));
245 }
246
247 if ( uidl.hasAttribute(ATTR_FOCUS) ) {
248 setFocus(uidl.getBooleanAttribute(ATTR_FOCUS));
249 }
250 }
251
252 }
253
254
255
256
257
258
259
260 protected CKEditor loadEditor(String inPageConfig) {
261 return (CKEditor) CKEditorService.loadEditor(paintableId,
262 VCKEditorTextField.this,
263 inPageConfig,
264 VCKEditorTextField.super.getOffsetWidth(),
265 VCKEditorTextField.super.getOffsetHeight());
266 }
267
268
269 @Override
270 public void onSave() {
271 if ( ckEditorIsReady && ! readOnly ) {
272
273 String data = ckEditor.getData();
274 if ( ! data.equals(dataBeforeEdit) ) {
275 clientToServer.updateVariable(paintableId, VAR_TEXT, data, false);
276 dataBeforeEdit = data;
277 }
278 clientToServer.sendPendingVariableChanges();
279 }
280 }
281
282
283 @Override
284 public void onBlur() {
285 if ( ckEditorIsReady ) {
286 boolean sendToServer = false;
287
288 if ( clientToServer.hasEventListeners(this, EventId.BLUR) ) {
289 sendToServer = true;
290 clientToServer.updateVariable(paintableId, EventId.BLUR, "", false);
291 }
292
293
294
295 if ( ! readOnly ) {
296 String data = ckEditor.getData();
297 if ( ! data.equals(dataBeforeEdit) ) {
298 clientToServer.updateVariable(paintableId, VAR_TEXT, data, false);
299 sendToServer = true;
300 dataBeforeEdit = data;
301 }
302 }
303
304 if (sendToServer) {
305 clientToServer.sendPendingVariableChanges();
306 }
307 }
308 }
309
310
311 @Override
312 public void onFocus() {
313 if ( ckEditorIsReady ) {
314 if ( clientToServer.hasEventListeners(this, EventId.FOCUS) ) {
315 clientToServer.updateVariable(paintableId, EventId.FOCUS, "", true);
316 }
317 }
318 }
319
320
321 @Override
322 public void onInstanceReady() {
323 ckEditor.instanceReady(this);
324
325 if ( writerRules != null ) {
326 Set<String> tagNameSet = writerRules.keySet();
327 for( String tagName : tagNameSet ) {
328 ckEditor.setWriterRules(tagName, writerRules.get(tagName));
329 }
330 writerRules = null;
331 }
332
333 if ( writerIndentationChars != null ) {
334 ckEditor.setWriterIndentationChars(writerIndentationChars);
335 writerIndentationChars = null;
336 }
337
338 if ( protectedSourceList != null ) {
339 for( String regex : protectedSourceList ) {
340 ckEditor.pushProtectedSource(regex);
341 }
342 protectedSourceList = null;
343 }
344
345 if ( dataBeforeEdit != null ) {
346 ckEditor.setData(dataBeforeEdit);
347 }
348
349 ckEditorIsReady = true;
350 ckEditor.setReadOnly(readOnly);
351
352 if (setFocusAfterReady) {
353 setFocus(true);
354 }
355
356 if ( setTabIndexAfterReady ) {
357 setTabIndex(tabIndex);
358 }
359
360 doResize();
361
362 if (protectedBody) {
363 ckEditor.protectBody(protectedBody);
364 }
365 ckeditorVersion = CKEditorService.version();
366 clientToServer.updateVariable(paintableId, VAR_VERSION, ckeditorVersion, true);
367 }
368
369 @Override
370 public void setWidth(String width) {
371 super.setWidth(width);
372 doResize();
373 }
374
375 @Override
376 public void setHeight(String height) {
377 super.setHeight(height);
378 doResize();
379 }
380
381 protected void doResize() {
382 if (ckEditorIsReady) {
383 Scheduler.get().scheduleDeferred(new ScheduledCommand() {
384 @Override
385 public void execute() {
386 ckEditor.resize(VCKEditorTextField.super.getOffsetWidth(), VCKEditorTextField.super.getOffsetHeight());
387 }
388 });
389 }
390 }
391
392 @Override
393 protected void onUnload() {
394 if ( ckEditor != null ) {
395 ckEditor.destroy();
396 ckEditor = null;
397 }
398 ckEditorIsReady = false;
399 }
400
401 @Override
402 public void onChange() {
403 if ( ckEditor != null && ! readOnly ) {
404 String data = ckEditor.getData();
405 if ( ! data.equals(dataBeforeEdit) ) {
406 clientToServer.updateVariable(paintableId, VAR_TEXT, data, immediate);
407 dataBeforeEdit = data;
408 }
409 }
410 }
411
412 @Override
413 public void onModeChange(String mode) {
414 if ( ckEditor != null ) {
415 if ( ! readOnly ) {
416 String data = ckEditor.getData();
417 if ( ! data.equals(dataBeforeEdit) ) {
418 clientToServer.updateVariable(paintableId, VAR_TEXT, data, true);
419 dataBeforeEdit = data;
420 }
421 }
422
423 if ("wysiwyg".equals(mode)) {
424 ckEditor.protectBody(protectedBody);
425 }
426 }
427 }
428
429 @Override
430 public void onDataReady() {
431 if ( ckEditor != null ) {
432 ckEditor.protectBody(protectedBody);
433 }
434 }
435
436 @Override
437 public int getTabIndex() {
438 if (ckEditorIsReady) {
439 return ckEditor.getTabIndex();
440 } else {
441 return tabIndex;
442 }
443 }
444
445 @Override
446 public void setTabIndex(int tabIndex) {
447 if (ckEditorIsReady) {
448 ckEditor.setTabIndex(tabIndex);
449 } else {
450 setTabIndexAfterReady = true;
451 }
452 this.tabIndex = tabIndex;
453 }
454
455 @Override
456 public void setAccessKey(char arg0) {
457 return;
458 }
459
460 @Override
461 public void setFocus(boolean arg0) {
462 if (arg0) {
463 if (ckEditorIsReady)
464 ckEditor.focus();
465 else
466 setFocusAfterReady = true;
467 } else {
468 setFocusAfterReady = false;
469 }
470 }
471
472 }