View Javadoc

1   /*
2    * Ext GWT 2.2.5 - Ext for GWT
3    * Copyright(c) 2007-2010, Ext JS, LLC.
4    * licensing@extjs.com
5    * 
6    * http://extjs.com/license
7    */
8   package com.extjs.gxt.ui.client.widget.form;
9   
10  import java.util.ArrayList;
11  import java.util.List;
12  
13  import com.extjs.gxt.ui.client.GXT;
14  import com.extjs.gxt.ui.client.core.El;
15  import com.extjs.gxt.ui.client.event.ButtonEvent;
16  import com.extjs.gxt.ui.client.event.ComponentEvent;
17  import com.extjs.gxt.ui.client.event.Events;
18  import com.extjs.gxt.ui.client.event.Listener;
19  import com.extjs.gxt.ui.client.event.SelectionListener;
20  import com.extjs.gxt.ui.client.util.Size;
21  import com.extjs.gxt.ui.client.widget.BoxComponent;
22  import com.extjs.gxt.ui.client.widget.ColorPalette;
23  import com.extjs.gxt.ui.client.widget.Component;
24  import com.extjs.gxt.ui.client.widget.ComponentHelper;
25  import com.extjs.gxt.ui.client.widget.ComponentManager;
26  import com.extjs.gxt.ui.client.widget.WidgetComponent;
27  import com.extjs.gxt.ui.client.widget.button.Button;
28  import com.extjs.gxt.ui.client.widget.button.ToggleButton;
29  import com.extjs.gxt.ui.client.widget.menu.ColorMenu;
30  import com.extjs.gxt.ui.client.widget.menu.Menu;
31  import com.extjs.gxt.ui.client.widget.tips.ToolTipConfig;
32  import com.extjs.gxt.ui.client.widget.toolbar.SeparatorToolItem;
33  import com.extjs.gxt.ui.client.widget.toolbar.ToolBar;
34  import com.google.gwt.core.client.GWT;
35  import com.google.gwt.event.dom.client.BlurEvent;
36  import com.google.gwt.event.dom.client.BlurHandler;
37  import com.google.gwt.event.dom.client.ChangeEvent;
38  import com.google.gwt.event.dom.client.ChangeHandler;
39  import com.google.gwt.event.dom.client.ClickEvent;
40  import com.google.gwt.event.dom.client.ClickHandler;
41  import com.google.gwt.event.dom.client.FocusEvent;
42  import com.google.gwt.event.dom.client.FocusHandler;
43  import com.google.gwt.event.dom.client.KeyDownEvent;
44  import com.google.gwt.event.dom.client.KeyDownHandler;
45  import com.google.gwt.event.dom.client.KeyUpEvent;
46  import com.google.gwt.event.dom.client.KeyUpHandler;
47  import com.google.gwt.user.client.DOM;
48  import com.google.gwt.user.client.Element;
49  import com.google.gwt.user.client.Window;
50  import com.google.gwt.user.client.ui.AbstractImagePrototype;
51  import com.google.gwt.user.client.ui.ListBox;
52  import com.google.gwt.user.client.ui.RichTextArea.BasicFormatter;
53  import com.google.gwt.user.client.ui.RichTextArea.ExtendedFormatter;
54  import com.google.gwt.user.client.ui.RichTextArea.FontSize;
55  import com.google.gwt.user.client.ui.RichTextArea.Justification;
56  import com.google.gwt.user.client.ui.impl.RichTextAreaImpl;
57  
58  /**
59   * Provides a lightweight HTML Editor component.
60   * 
61   * <p />
62   * <b>Note: The focus/blur and validation marking functionality inherited from
63   * {@link Field} is NOT supported by this editor.</b>
64   * 
65   * <p />
66   * An Editor is a sensitive component that can't be used in all spots standard
67   * fields can be used. Putting an Editor within any element that has display set
68   * to 'none' can cause problems in Safari and Firefox due to their default
69   * iframe reloading bugs.
70   * 
71   * 
72   * <dl>
73   * <dt><b>Events:</b></dt>
74   * 
75   * <dd><b>BeforeSync</b> : HtmlEditorEvent(htmlEditor, change)<br>
76   * <div>Fires before the iframe editor is updated with content from the
77   * textarea.</div>
78   * <ul>
79   * <li>htmlEditor : this</li>
80   * <li>change : true for edit mode</li>
81   * </ul>
82   * </dd>
83   * 
84   * <dd><b>Sync</b> : HtmlEditorEvent(htmlEditor, change)<br>
85   * <div>Fires when the iframe editor is updated with content from the
86   * textarea.</div>
87   * <ul>
88   * <li>htmlEditor : this</li>
89   * <li>change : true for edit mode</li>
90   * </ul>
91   * </dd>
92   * 
93   * <dd><b>EditModeChange</b> : HtmlEditorEvent(htmlEditor, change)<br>
94   * <div>Fires when the editor switches edit modes.</div>
95   * <ul>
96   * <li>htmlEditor : this</li>
97   * <li>change : true for edit mode</li>
98   * </ul>
99   * </dd>
100  * 
101  * </dl>
102  */
103 @SuppressWarnings("deprecation")
104 public class HtmlEditor extends Field<String> {
105 
106   public class HtmlEditorImages extends FieldImages {
107     private AbstractImagePrototype bold = GXT.IMAGES.editor_bold();
108     private AbstractImagePrototype fontColor = GXT.IMAGES.editor_font_color();
109     private AbstractImagePrototype fontDecrease = GXT.IMAGES.editor_font_decrease();
110     private AbstractImagePrototype fontHighlight = GXT.IMAGES.editor_font_highlight();
111     private AbstractImagePrototype fontIncrease = GXT.IMAGES.editor_font_increase();
112     private AbstractImagePrototype italic = GXT.IMAGES.editor_italic();
113     private AbstractImagePrototype justifyCenter = GXT.IMAGES.editor_justify_center();
114     private AbstractImagePrototype justifyLeft = GXT.IMAGES.editor_justify_left();
115     private AbstractImagePrototype justifyRight = GXT.IMAGES.editor_justify_right();
116     private AbstractImagePrototype link = GXT.IMAGES.editor_link();
117     private AbstractImagePrototype ol = GXT.IMAGES.editor_ol();
118     private AbstractImagePrototype source = GXT.IMAGES.editor_source();
119     private AbstractImagePrototype ul = GXT.IMAGES.editor_ul();
120     private AbstractImagePrototype underline = GXT.IMAGES.editor_underline();
121 
122     public AbstractImagePrototype getBold() {
123       return bold;
124     }
125 
126     public AbstractImagePrototype getFontColor() {
127       return fontColor;
128     }
129 
130     public AbstractImagePrototype getFontDecrease() {
131       return fontDecrease;
132     }
133 
134     public AbstractImagePrototype getFontHighlight() {
135       return fontHighlight;
136     }
137 
138     public AbstractImagePrototype getFontIncrease() {
139       return fontIncrease;
140     }
141 
142     public AbstractImagePrototype getItalic() {
143       return italic;
144     }
145 
146     public AbstractImagePrototype getJustifyCenter() {
147       return justifyCenter;
148     }
149 
150     public AbstractImagePrototype getJustifyLeft() {
151       return justifyLeft;
152     }
153 
154     public AbstractImagePrototype getJustifyRight() {
155       return justifyRight;
156     }
157 
158     public AbstractImagePrototype getLink() {
159       return link;
160     }
161 
162     public AbstractImagePrototype getOl() {
163       return ol;
164     }
165 
166     public AbstractImagePrototype getSource() {
167       return source;
168     }
169 
170     public AbstractImagePrototype getUl() {
171       return ul;
172     }
173 
174     public AbstractImagePrototype getUnderline() {
175       return underline;
176     }
177 
178     public void setBold(AbstractImagePrototype bold) {
179       this.bold = bold;
180     }
181 
182     public void setFontColor(AbstractImagePrototype fontColor) {
183       this.fontColor = fontColor;
184     }
185 
186     public void setFontDecrease(AbstractImagePrototype fontDecrease) {
187       this.fontDecrease = fontDecrease;
188     }
189 
190     public void setFontHighlight(AbstractImagePrototype fontHighlight) {
191       this.fontHighlight = fontHighlight;
192     }
193 
194     public void setFontIncrease(AbstractImagePrototype fontIncrease) {
195       this.fontIncrease = fontIncrease;
196     }
197 
198     public void setItalic(AbstractImagePrototype italic) {
199       this.italic = italic;
200     }
201 
202     public void setJustifyCenter(AbstractImagePrototype justifyCenter) {
203       this.justifyCenter = justifyCenter;
204     }
205 
206     public void setJustifyLeft(AbstractImagePrototype justifyLeft) {
207       this.justifyLeft = justifyLeft;
208     }
209 
210     public void setJustifyRight(AbstractImagePrototype justifyRight) {
211       this.justifyRight = justifyRight;
212     }
213 
214     public void setLink(AbstractImagePrototype link) {
215       this.link = link;
216     }
217 
218     public void setOl(AbstractImagePrototype ol) {
219       this.ol = ol;
220     }
221 
222     public void setSource(AbstractImagePrototype source) {
223       this.source = source;
224     }
225 
226     public void setUl(AbstractImagePrototype ul) {
227       this.ul = ul;
228     }
229 
230     public void setUnderline(AbstractImagePrototype underline) {
231       this.underline = underline;
232     }
233   }
234 
235   public class HtmlEditorMessages extends FieldMessages {
236     private String backColorTipText = GXT.MESSAGES.htmlEditor_backColorTipText();
237     private String backColorTipTitle = GXT.MESSAGES.htmlEditor_backColorTipTitle();
238     private String boldTipText = GXT.MESSAGES.htmlEditor_boldTipText();
239     private String boldTipTitle = GXT.MESSAGES.htmlEditor_boldTipTitle();
240     private String createLinkText = GXT.MESSAGES.htmlEditor_createLinkText();
241     private String decreaseFontSizeTipText = GXT.MESSAGES.htmlEditor_decreaseFontSizeTipText();
242     private String decreaseFontSizeTipTitle = GXT.MESSAGES.htmlEditor_decreaseFontSizeTipTitle();
243     private String foreColorTipText = GXT.MESSAGES.htmlEditor_foreColorTipText();
244     private String foreColorTipTitle = GXT.MESSAGES.htmlEditor_foreColorTipTitle();
245     private String increaseFontSizeTipText = GXT.MESSAGES.htmlEditor_increaseFontSizeTipText();
246     private String increaseFontSizeTipTitle = GXT.MESSAGES.htmlEditor_increaseFontSizeTipTitle();
247     private String italicTipText = GXT.MESSAGES.htmlEditor_italicTipText();
248     private String italicTipTitle = GXT.MESSAGES.htmlEditor_italicTipTitle();
249     private String justifyCenterTipText = GXT.MESSAGES.htmlEditor_justifyCenterTipText();
250     private String justifyCenterTipTitle = GXT.MESSAGES.htmlEditor_justifyCenterTipTitle();
251     private String justifyLeftTipText = GXT.MESSAGES.htmlEditor_justifyLeftTipText();
252     private String justifyLeftTipTitle = GXT.MESSAGES.htmlEditor_justifyLeftTipTitle();
253     private String justifyRightTipText = GXT.MESSAGES.htmlEditor_justifyRightTipText();
254     private String justifyRightTipTitle = GXT.MESSAGES.htmlEditor_justifyRightTipTitle();
255     private String linkTipText = GXT.MESSAGES.htmlEditor_linkTipText();
256     private String linkTipTitle = GXT.MESSAGES.htmlEditor_linkTipTitle();
257     private String olTipText = GXT.MESSAGES.htmlEditor_olTipText();
258     private String olTipTitle = GXT.MESSAGES.htmlEditor_olTipTitle();
259     private String sourceEditTipText = GXT.MESSAGES.htmlEditor_sourceEditTipText();
260     private String sourceEditTipTitle = GXT.MESSAGES.htmlEditor_sourceEditTipTitle();
261     private String ulTipText = GXT.MESSAGES.htmlEditor_ulTipText();
262     private String ulTipTitle = GXT.MESSAGES.htmlEditor_ulTipTitle();
263     private String underlineTipText = GXT.MESSAGES.htmlEditor_underlineTipText();
264     private String underlineTipTitle = GXT.MESSAGES.htmlEditor_underlineTipTitle();
265 
266     public String getBackColorTipText() {
267       return backColorTipText;
268     }
269 
270     public String getBackColorTipTitle() {
271       return backColorTipTitle;
272     }
273 
274     public String getBoldTipText() {
275       return boldTipText;
276     }
277 
278     public String getBoldTipTitle() {
279       return boldTipTitle;
280     }
281 
282     public String getCreateLinkText() {
283       return createLinkText;
284     }
285 
286     public String getDecreaseFontSizeTipText() {
287       return decreaseFontSizeTipText;
288     }
289 
290     public String getDecreaseFontSizeTipTitle() {
291       return decreaseFontSizeTipTitle;
292     }
293 
294     public String getForColorTipTitle() {
295       return foreColorTipTitle;
296     }
297 
298     public String getForeColorTipText() {
299       return foreColorTipText;
300     }
301 
302     public String getIncreaseFontSizeTipText() {
303       return increaseFontSizeTipText;
304     }
305 
306     public String getIncreaseFontSizeTipTitle() {
307       return increaseFontSizeTipTitle;
308     }
309 
310     public String getItalicTipText() {
311       return italicTipText;
312     }
313 
314     public String getItalicTipTitle() {
315       return italicTipTitle;
316     }
317 
318     public String getJustifyCenterTipText() {
319       return justifyCenterTipText;
320     }
321 
322     public String getJustifyCenterTipTitle() {
323       return justifyCenterTipTitle;
324     }
325 
326     public String getJustifyLeftTipText() {
327       return justifyLeftTipText;
328     }
329 
330     public String getJustifyLeftTipTitle() {
331       return justifyLeftTipTitle;
332     }
333 
334     public String getJustifyRightTipText() {
335       return justifyRightTipText;
336     }
337 
338     public String getJustifyRightTipTitle() {
339       return justifyRightTipTitle;
340     }
341 
342     public String getLinkTipText() {
343       return linkTipText;
344     }
345 
346     public String getLinkTipTitle() {
347       return linkTipTitle;
348     }
349 
350     public String getOlTipText() {
351       return olTipText;
352     }
353 
354     public String getOlTipTitle() {
355       return olTipTitle;
356     }
357 
358     public String getSourceEditTipText() {
359       return sourceEditTipText;
360     }
361 
362     public String getSourceEditTipTitle() {
363       return sourceEditTipTitle;
364     }
365 
366     public String getUlTipText() {
367       return ulTipText;
368     }
369 
370     public String getUlTipTitle() {
371       return ulTipTitle;
372     }
373 
374     public String getUnderlineTipText() {
375       return underlineTipText;
376     }
377 
378     public String getUnderlineTipTitle() {
379       return underlineTipTitle;
380     }
381 
382     public void setBackColorTipText(String backColorTipText) {
383       this.backColorTipText = backColorTipText;
384     }
385 
386     public void setBackColorTipTitle(String backColorTipTitle) {
387       this.backColorTipTitle = backColorTipTitle;
388     }
389 
390     public void setBoldTipText(String boldTipText) {
391       this.boldTipText = boldTipText;
392     }
393 
394     public void setBoldTipTitle(String boldTipTitle) {
395       this.boldTipTitle = boldTipTitle;
396     }
397 
398     public void setCreateLinkText(String createLinkText) {
399       this.createLinkText = createLinkText;
400     }
401 
402     public void setDecreaseFontSizeTipText(String decreaseFontSizeTipText) {
403       this.decreaseFontSizeTipText = decreaseFontSizeTipText;
404     }
405 
406     public void setDecreaseFontSizeTipTitle(String decreaseFontSizeTipTitle) {
407       this.decreaseFontSizeTipTitle = decreaseFontSizeTipTitle;
408     }
409 
410     public void setForeColorTipText(String foreColorTipText) {
411       this.foreColorTipText = foreColorTipText;
412     }
413 
414     public void setForeColorTipTitle(String foreColorTipTitle) {
415       this.foreColorTipTitle = foreColorTipTitle;
416     }
417 
418     public void setIncreaseFontSizeTipText(String increaseFontSizeTipText) {
419       this.increaseFontSizeTipText = increaseFontSizeTipText;
420     }
421 
422     public void setIncreaseFontSizeTipTitle(String increaseFontSizeTipTitle) {
423       this.increaseFontSizeTipTitle = increaseFontSizeTipTitle;
424     }
425 
426     public void setItalicTipText(String italicTipText) {
427       this.italicTipText = italicTipText;
428     }
429 
430     public void setItalicTipTitle(String italicTipTitle) {
431       this.italicTipTitle = italicTipTitle;
432     }
433 
434     public void setJustifyCenterTipText(String justifyCenterTipText) {
435       this.justifyCenterTipText = justifyCenterTipText;
436     }
437 
438     public void setJustifyCenterTipTitle(String justifyCenterTipTitle) {
439       this.justifyCenterTipTitle = justifyCenterTipTitle;
440     }
441 
442     public void setJustifyLeftTipText(String justifyLeftTipText) {
443       this.justifyLeftTipText = justifyLeftTipText;
444     }
445 
446     public void setJustifyLeftTipTitle(String justifyLeftTipTitle) {
447       this.justifyLeftTipTitle = justifyLeftTipTitle;
448     }
449 
450     public void setJustifyRightTipText(String justifyRightTipText) {
451       this.justifyRightTipText = justifyRightTipText;
452     }
453 
454     public void setJustifyRightTipTitle(String justifyRightTipTitle) {
455       this.justifyRightTipTitle = justifyRightTipTitle;
456     }
457 
458     public void setLinkTipText(String linkTipText) {
459       this.linkTipText = linkTipText;
460     }
461 
462     public void setLinkTipTitle(String linkTipTitle) {
463       this.linkTipTitle = linkTipTitle;
464     }
465 
466     public void setOlTipText(String olTipText) {
467       this.olTipText = olTipText;
468     }
469 
470     public void setOlTipTitle(String olTipTitle) {
471       this.olTipTitle = olTipTitle;
472     }
473 
474     public void setSourceEditTipText(String sourceEditTipText) {
475       this.sourceEditTipText = sourceEditTipText;
476     }
477 
478     public void setSourceEditTipTitle(String sourceEditTipTitle) {
479       this.sourceEditTipTitle = sourceEditTipTitle;
480     }
481 
482     public void setUlTipText(String ulTipText) {
483       this.ulTipText = ulTipText;
484     }
485 
486     public void setUlTipTitle(String ulTipTitle) {
487       this.ulTipTitle = ulTipTitle;
488     }
489 
490     public void setUnderlineTipText(String underlineTipText) {
491       this.underlineTipText = underlineTipText;
492     }
493 
494     public void setUnderlineTipTitle(String underlineTipTitle) {
495       this.underlineTipTitle = underlineTipTitle;
496     }
497 
498   }
499 
500   protected class EventHandler implements KeyDownHandler, ClickHandler, KeyUpHandler, FocusHandler, BlurHandler {
501 
502     public void onBlur(BlurEvent event) {
503 
504     }
505 
506     public void onClick(ClickEvent event) {
507       updateStatus();
508       syncValue();
509 
510       ArrayList<Component> col = new ArrayList<Component>(ComponentManager.get().getAll());
511       for (Component c : col) {
512         if (c instanceof TriggerField<?>) {
513           ((TriggerField<?>) c).triggerBlur(null);
514         } else if (c instanceof Menu) {
515           ((Menu) c).hide(true);
516         }
517       }
518       impl.setFocus(true);
519     }
520 
521     public void onFocus(FocusEvent event) {
522     }
523 
524     public void onKeyDown(KeyDownEvent event) {
525       onEditorKeyDown(event);
526     }
527 
528     public void onKeyUp(KeyUpEvent event) {
529       updateStatus();
530       syncValue();
531     }
532   }
533 
534   protected class rte extends BoxComponent {
535     @Override
536     protected void onAttach() {
537       super.onAttach();
538       impl.initElement();
539     }
540 
541     @Override
542     protected void onDetach() {
543       super.onDetach();
544       impl.uninitElement();
545     }
546 
547     protected void onRender(Element target, int index) {
548       Element e = (Element) impl.getElement();
549       e.setPropertyInt("frameBorder", 0);
550       setElement(e, target, index);
551 
552       addDomHandler(handler, ClickEvent.getType());
553       addDomHandler(handler, FocusEvent.getType());
554       addDomHandler(handler, BlurEvent.getType());
555       addDomHandler(handler, KeyUpEvent.getType());
556       addDomHandler(handler, KeyDownEvent.getType());
557     }
558   }
559 
560   protected FontSize activeFontSize = FontSize.SMALL;
561 
562   protected Button backcolor;
563 
564   // the toolbar buttons
565   protected ToggleButton bold;
566   protected SelectionListener<ButtonEvent> btnListener;
567 
568   protected Button decreasefontsize;
569   protected List<FontSize> fontSizesConstants = new ArrayList<FontSize>();
570   protected Button forecolor;
571   protected EventHandler handler = new EventHandler();
572   protected RichTextAreaImpl impl = GWT.create(RichTextAreaImpl.class);
573   protected Button increasefontsize;
574   protected ToggleButton italic;
575   protected Button justifyCenter;
576   protected Button justifyLeft;
577   protected Button justifyRight;
578   protected Button link;
579   protected Button ol;
580   protected rte rte;
581   protected ToggleButton sourceEdit;
582   protected ToolBar tb;
583   protected El textarea;
584   protected Button ul;
585 
586   protected ToggleButton underline;
587   private boolean enableAlignments = true;
588 
589   private boolean enableColors = true;
590   private boolean enableFont = true;
591   private boolean enableFontSize = true;
592   private boolean enableFormat = true;
593   private boolean enableLinks = true;
594   private boolean enableLists = true;
595   private boolean showToolbar = true;
596   private boolean sourceEditMode = true;
597 
598   public HtmlEditor() {
599     super();
600     disabledStyle = null;
601     fontSizesConstants.add(FontSize.XX_SMALL);
602     fontSizesConstants.add(FontSize.X_SMALL);
603     fontSizesConstants.add(FontSize.SMALL);
604     fontSizesConstants.add(FontSize.MEDIUM);
605     fontSizesConstants.add(FontSize.LARGE);
606     fontSizesConstants.add(FontSize.X_LARGE);
607     fontSizesConstants.add(FontSize.XX_LARGE);
608     setSize(500, 300);
609 
610     messages = new HtmlEditorMessages();
611   }
612 
613   /**
614    * Gets the basic rich text formatting interface.
615    * 
616    * @return <code>null</code> if basic formatting is not supported
617    */
618   public BasicFormatter getBasicFormatter() {
619     if (impl instanceof BasicFormatter) {
620       return (BasicFormatter) impl;
621     }
622     return null;
623   }
624 
625   /**
626    * Gets the full rich text formatting interface.
627    * 
628    * @return <code>null</code> if full formatting is not supported
629    */
630   public ExtendedFormatter getExtendedFormatter() {
631     if (impl instanceof ExtendedFormatter) {
632       return (ExtendedFormatter) impl;
633     }
634     return null;
635   }
636 
637   @Override
638   public HtmlEditorImages getImages() {
639     if (images == null) {
640       images = new HtmlEditorImages();
641     }
642     return (HtmlEditorImages) images;
643   }
644 
645   @Override
646   public HtmlEditorMessages getMessages() {
647     return (HtmlEditorMessages) messages;
648   }
649 
650   @Override
651   public String getRawValue() {
652     if (sourceEdit != null && sourceEdit.isPressed()) {
653       pushValue();
654     } else {
655       syncValue();
656     }
657 
658     String value = super.getRawValue();
659     if ("&#8203;".equals(value)) {
660       return "";
661     } else {
662       return value;
663     }
664   }
665 
666   public boolean isEnableAlignments() {
667     return enableAlignments;
668   }
669 
670   public boolean isEnableColors() {
671     return enableColors;
672   }
673 
674   public boolean isEnableFont() {
675     return enableFont;
676   }
677 
678   public boolean isEnableFontSize() {
679     return enableFontSize;
680   }
681 
682   public boolean isEnableFormat() {
683     return enableFormat;
684   }
685 
686   public boolean isEnableLinks() {
687     return enableLinks;
688   }
689 
690   public boolean isEnableLists() {
691     return enableLists;
692   }
693 
694   public boolean isShowToolbar() {
695     return showToolbar;
696   }
697 
698   public boolean isSourceEditMode() {
699     return sourceEditMode;
700   }
701 
702   public void pushValue() {
703     if (isRendered()) {
704       impl.setHTML(getInputEl().getValue());
705     }
706   }
707 
708   public void setEnableAlignments(boolean enableAlignments) {
709     this.enableAlignments = enableAlignments;
710   }
711 
712   public void setEnableColors(boolean enableColors) {
713     this.enableColors = enableColors;
714   }
715 
716   public void setEnableFont(boolean enableFont) {
717     this.enableFont = enableFont;
718   }
719 
720   public void setEnableFontSize(boolean enableFontSize) {
721     this.enableFontSize = enableFontSize;
722   }
723 
724   public void setEnableFormat(boolean enableFormat) {
725     this.enableFormat = enableFormat;
726   }
727 
728   public void setEnableLinks(boolean enableLinks) {
729     this.enableLinks = enableLinks;
730   }
731 
732   public void setEnableLists(boolean enableLists) {
733     this.enableLists = enableLists;
734   }
735 
736   @Override
737   public void setRawValue(String value) {
738     impl.setHTML(value);
739     super.setRawValue(value);
740   }
741 
742   public void setShowToolbar(boolean showToolbar) {
743     this.showToolbar = showToolbar;
744   }
745 
746   public void setSourceEditMode(boolean mode) {
747     assertPreRender();
748     sourceEditMode = mode;
749   }
750 
751   @Override
752   public void setValue(String value) {
753     impl.setHTML(value);
754     super.setValue(value);
755   }
756 
757   public void syncValue() {
758     if (isRendered()) {
759       getInputEl().setValue(impl.getHTML());
760     }
761   }
762 
763   @Override
764   public boolean validate(boolean silent) {
765     return true;
766   }
767 
768   @Override
769   protected void afterRender() {
770     super.afterRender();
771     if (GXT.isHighContrastMode) {
772       setHighContrastImage(sourceEdit, "tb-source.gif");
773       setHighContrastImage(increasefontsize, "tb-font-increase.gif");
774       setHighContrastImage(decreasefontsize, "tb-font-decrease.gif");
775       setHighContrastImage(forecolor, "tb-font-color.gif");
776       setHighContrastImage(backcolor, "tb-font-highlight.gif");
777       setHighContrastImage(bold, "tb-bold.gif");
778       setHighContrastImage(italic, "tb-italic.gif");
779       setHighContrastImage(underline, "tb-underline.gif");
780       setHighContrastImage(justifyLeft, "tb-justify-left.gif");
781       setHighContrastImage(justifyCenter, "tb-justify-center.gif");
782       setHighContrastImage(justifyRight, "tb-justify-right.gif");
783       setHighContrastImage(ol, "tb-ol.gif");
784       setHighContrastImage(ul, "tb-ul.gif");
785       setHighContrastImage(link, "tb-link.gif");
786     }
787   }
788 
789   protected Button createButton(AbstractImagePrototype icon, final String tt, String toolTipTitle) {
790     Button item = new Button() {
791       @Override
792       protected void afterRender() {
793         super.afterRender();
794         if (GXT.isAriaEnabled()) buttonEl.dom.setTitle(tt);
795       }
796     };
797     item.setIcon(icon);
798     item.setTabIndex(-1);
799 
800     ToolTipConfig cfg = new ToolTipConfig(toolTipTitle, tt);
801     item.setToolTip(cfg);
802 
803     if (GXT.isAriaEnabled()) {
804       item.setData("gxt-menutext", toolTipTitle);
805     }
806 
807     item.addSelectionListener(btnListener);
808     return item;
809   }
810 
811   protected Button createColorButton(AbstractImagePrototype icon, String toolTip, String toolTipTitle,
812       Listener<ComponentEvent> listener) {
813     Button item = new Button();
814     item.setIcon(icon);
815     item.setTabIndex(-1);
816 
817     ToolTipConfig cfg = new ToolTipConfig(toolTipTitle, toolTip);
818     item.setToolTip(cfg);
819 
820     if (GXT.isAriaEnabled()) {
821       item.setData("gxt-menutext", toolTipTitle);
822     }
823 
824     ColorMenu menu = new ColorMenu();
825     menu.getColorPalette().addListener(Events.Select, listener);
826     item.setMenu(menu);
827     return item;
828   }
829 
830   protected ToggleButton createToggleButton(AbstractImagePrototype icon, final String tt, String toolTipTitle) {
831     ToggleButton item = new ToggleButton() {
832       @Override
833       protected void afterRender() {
834         super.afterRender();
835         if (GXT.isAriaEnabled()) buttonEl.dom.setTitle(tt);
836       }
837     };
838     item.setTabIndex(-1);
839 
840     ToolTipConfig cfg = new ToolTipConfig(toolTipTitle, tt);
841     item.setToolTip(cfg);
842 
843     if (GXT.isAriaEnabled()) {
844       item.setData("gxt-menutext", toolTipTitle);
845     }
846 
847     item.setIcon(icon);
848     item.addSelectionListener(btnListener);
849     return item;
850   }
851 
852   protected void doAttachChildren() {
853     super.doAttachChildren();
854     ComponentHelper.doAttach(tb);
855     ComponentHelper.doAttach(rte);
856   }
857 
858   protected void doDetachChildren() {
859     super.doAttachChildren();
860     ComponentHelper.doDetach(tb);
861     ComponentHelper.doDetach(rte);
862   }
863 
864   @Override
865   protected El getInputEl() {
866     return textarea;
867   }
868 
869   @Override
870   protected void onAttach() {
871     super.onAttach();
872     el().repaint();
873   }
874 
875   @Override
876   protected void onBlur(ComponentEvent ce) {
877 
878   }
879 
880   @Override
881   protected void onDisable() {
882     super.onDisable();
883     if (tb != null) {
884       tb.disable();
885     }
886     mask();
887   }
888 
889   protected void onEditorKeyDown(KeyDownEvent e) {
890     int kc = e.getNativeKeyCode();
891     switch (kc) {
892       case 66:
893         if (e.isControlKeyDown()) {
894           e.stopPropagation();
895           e.preventDefault();
896           getBasicFormatter().toggleBold();
897         }
898         break;
899       case 73:
900         if (e.isControlKeyDown()) {
901           e.stopPropagation();
902           e.preventDefault();
903           getBasicFormatter().toggleItalic();
904         }
905         break;
906       case 85:
907         if (e.isControlKeyDown()) {
908           e.stopPropagation();
909           e.preventDefault();
910           getBasicFormatter().toggleUnderline();
911         }
912         break;
913     }
914   }
915 
916   @Override
917   protected void onEnable() {
918     super.onEnable();
919     if (tb != null) {
920       tb.enable();
921     }
922     unmask();
923   }
924 
925   @Override
926   protected void onFocus(ComponentEvent ce) {
927     if (sourceEdit == null || !sourceEdit.isPressed()) {
928       impl.setFocus(true);
929     } else {
930       textarea.focus();
931     }
932   }
933 
934   @Override
935   protected void onRender(Element target, int index) {
936     setElement(DOM.createDiv(), target, index);
937     addStyleName("x-html-editor-wrap");
938     
939     if (GXT.isIE6) {
940       getElement().getStyle().setProperty("position", "relative");
941     }
942  
943     rte = new rte();
944 
945     textarea = new El(DOM.createTextArea());
946     textarea.addStyleName("x-hidden");
947     textarea.addStyleName("x-form-textarea");
948     textarea.addStyleName("x-form-field");
949     textarea.setStyleAttribute("border", "0 none");
950     el().appendChild(textarea.dom);
951     rte.render(el().dom);
952 
953     if (!GXT.isAriaEnabled()) {
954       setupToolbar();
955     }
956 
957     super.onRender(target, index);
958 
959     el().selectNode("iframe").setTitle(getFieldLabel() + " HTML Editor");
960   }
961 
962   @Override
963   protected void onResize(int width, int height) {
964     super.onResize(width, height);
965 
966     int aw = width;
967     int ah = height;
968 
969     Size frameWidth = el().getFrameSize();
970     aw -= frameWidth.width;
971     ah -= frameWidth.height;
972 
973     if (showToolbar && !GXT.isAriaEnabled()) {
974       el().down(".x-html-editor-tb").setWidth(aw, true);
975       tb.setWidth(aw);
976       ah -= tb.getHeight();
977     }
978     rte.setSize(width == -1 ? -1 : aw, height == -1 ? -1 : ah);
979 
980     textarea.setSize(width == -1 ? -1 : aw, height == -1 ? -1 : ah, true);
981   }
982 
983   protected void setHighContrastImage(Button btn, String image) {
984     if (btn != null) {
985       btn.el().selectNode("button").setWidth(18).setInnerHtml(
986           "<img src='" + GXT.RESOURCES_URL + "/images/default/editor/" + image + "'>");
987     }
988   }
989 
990   protected void setupToolbar() {
991     if (showToolbar) {
992       btnListener = new SelectionListener<ButtonEvent>() {
993 
994         @Override
995         public void componentSelected(ButtonEvent ce) {
996           Component item = ce.getComponent();
997           if (item == bold) {
998             getBasicFormatter().toggleBold();
999           } else if (item == italic) {
1000             getBasicFormatter().toggleItalic();
1001           } else if (item == underline) {
1002             getBasicFormatter().toggleUnderline();
1003           } else if (item == sourceEdit) {
1004             toggleSourceEditMode();
1005             focus();
1006           } else if (item == ol) {
1007             getExtendedFormatter().insertOrderedList();
1008           } else if (item == ul) {
1009             getExtendedFormatter().insertUnorderedList();
1010           } else if (item == link) {
1011             String link = Window.prompt(getMessages().getCreateLinkText(), "http://");
1012             if (link != null && link.length() > 0) {
1013               getExtendedFormatter().createLink(link);
1014             } else {
1015               getExtendedFormatter().removeLink();
1016             }
1017           } else if (item == justifyLeft) {
1018             getBasicFormatter().setJustification(Justification.LEFT);
1019           } else if (item == justifyCenter) {
1020             getBasicFormatter().setJustification(Justification.CENTER);
1021           } else if (item == justifyRight) {
1022             getBasicFormatter().setJustification(Justification.RIGHT);
1023           } else if (item == increasefontsize) {
1024             int i = fontSizesConstants.indexOf(activeFontSize);
1025             if (i < (fontSizesConstants.size() - 1)) {
1026               i++;
1027               activeFontSize = fontSizesConstants.get(i);
1028               getBasicFormatter().setFontSize(activeFontSize);
1029             } else {
1030               // brings focus back to the editor
1031               focus();
1032             }
1033           } else if (item == decreasefontsize) {
1034             int i = fontSizesConstants.indexOf(activeFontSize);
1035             if (i > 0) {
1036               i--;
1037               activeFontSize = fontSizesConstants.get(i);
1038               getBasicFormatter().setFontSize(activeFontSize);
1039             } else {
1040               // brings focus back to the editor
1041               focus();
1042             }
1043           }
1044         }
1045       };
1046 
1047       HtmlEditorImages g = getImages();
1048       HtmlEditorMessages m = getMessages();
1049 
1050       tb = new ToolBar();
1051       tb.addListener(Events.OnClick, new Listener<ComponentEvent>() {
1052         public void handleEvent(ComponentEvent be) {
1053           if (fly(be.getTarget()).findParent(".x-toolbar-cell", 10) != null) {
1054             be.cancelBubble();
1055           }
1056         }
1057       });
1058       ComponentHelper.setParent(this, tb);
1059       if (sourceEditMode) {
1060         tb.add(sourceEdit = createToggleButton(g.getSource(), m.getSourceEditTipText(), m.getSourceEditTipTitle()));
1061         tb.add(new SeparatorToolItem());
1062       }
1063 
1064       if (getBasicFormatter() != null) {
1065         if (enableFont) {
1066           final ListBox fonts = new ListBox();
1067           fonts.addItem("");
1068           fonts.addItem("Arial");
1069           fonts.addItem("Times New Roman");
1070           fonts.addItem("Verdana");
1071           fonts.setItemSelected(0, true);
1072           fonts.addChangeHandler(new ChangeHandler() {
1073 
1074             public void onChange(ChangeEvent event) {
1075               int index = fonts.getSelectedIndex();
1076               if (index != 0) {
1077                 getBasicFormatter().setFontName(fonts.getItemText(index));
1078               }
1079               fonts.setItemSelected(0, true);
1080             }
1081           });
1082 
1083           tb.add(new WidgetComponent(fonts));
1084           tb.add(new SeparatorToolItem());
1085         }
1086         if (enableFontSize) {
1087           tb.add(increasefontsize = createButton(g.getFontIncrease(), m.getIncreaseFontSizeTipText(),
1088               m.getIncreaseFontSizeTipTitle()));
1089           tb.add(decreasefontsize = createButton(g.getFontDecrease(), m.getDecreaseFontSizeTipText(),
1090               m.getDecreaseFontSizeTipTitle()));
1091 
1092           tb.add(new SeparatorToolItem());
1093         }
1094         if (enableFormat) {
1095           tb.add(bold = createToggleButton(g.getBold(), m.getBoldTipText(), m.getBoldTipTitle()));
1096           tb.add(italic = createToggleButton(g.getItalic(), m.getItalicTipText(), m.getItalicTipTitle()));
1097           tb.add(underline = createToggleButton(g.getUnderline(), m.getUnderlineTipText(), m.getUnderlineTipTitle()));
1098           tb.add(new SeparatorToolItem());
1099         }
1100         if (enableAlignments) {
1101           tb.add(justifyLeft = createButton(g.getJustifyLeft(), m.getJustifyLeftTipText(), m.getJustifyLeftTipTitle()));
1102           tb.add(justifyCenter = createButton(g.getJustifyCenter(), m.getJustifyCenterTipText(),
1103               m.getJustifyCenterTipTitle()));
1104           tb.add(justifyRight = createButton(g.getJustifyRight(), m.getJustifyRightTipText(),
1105               m.getJustifyRightTipTitle()));
1106           tb.add(new SeparatorToolItem());
1107         }
1108       }
1109 
1110       if (getExtendedFormatter() != null) {
1111         if (enableLists) {
1112           tb.add(ol = createButton(g.getOl(), m.getOlTipText(), m.getOlTipTitle()));
1113           tb.add(ul = createButton(g.getUl(), m.getUlTipText(), m.getUlTipTitle()));
1114           tb.add(new SeparatorToolItem());
1115         }
1116         if (enableLinks) {
1117           tb.add(link = createButton(g.getLink(), m.getLinkTipText(), m.getLinkTipTitle()));
1118           tb.add(new SeparatorToolItem());
1119         }
1120         if (enableColors) {
1121           tb.add(forecolor = createColorButton(g.getFontColor(), m.getForeColorTipText(), m.getForColorTipTitle(),
1122               new Listener<ComponentEvent>() {
1123                 public void handleEvent(ComponentEvent be) {
1124                   getBasicFormatter().setForeColor(((ColorPalette) be.getComponent()).getValue());
1125                 }
1126               }));
1127           tb.add(backcolor = createColorButton(g.getFontHighlight(), m.getBackColorTipText(), m.getBackColorTipTitle(),
1128               new Listener<ComponentEvent>() {
1129                 public void handleEvent(ComponentEvent be) {
1130                   getBasicFormatter().setBackColor(((ColorPalette) be.getComponent()).getValue());
1131                 }
1132               }));
1133         }
1134       }
1135       Element e = DOM.createDiv();
1136       // needed for display issues
1137       e.getStyle().setProperty("position", "relative");
1138       e.setClassName("x-html-editor-tb");
1139       el().insertFirst(e);
1140       tb.render(e);
1141 
1142     }
1143   }
1144 
1145   protected void toggleSourceEditMode() {
1146     if (sourceEdit.isPressed()) {
1147       syncValue();
1148       rte.el().addStyleName("x-hidden");
1149       textarea.removeStyleName("x-hidden");
1150     } else {
1151       pushValue();
1152       rte.el().removeStyleName("x-hidden");
1153       textarea.addStyleName("x-hidden");
1154     }
1155     for (Component item : tb.getItems()) {
1156       if (item != sourceEdit) {
1157         item.setEnabled(!item.isEnabled());
1158       }
1159     }
1160   }
1161 
1162   protected void updateStatus() {
1163     if (showToolbar && rendered && !GXT.isAriaEnabled()) {
1164       BasicFormatter basic = getBasicFormatter();
1165       if (basic != null) {
1166         bold.toggle(basic.isBold());
1167         underline.toggle(basic.isUnderlined());
1168         italic.toggle(basic.isItalic());
1169       }
1170     }
1171   }
1172 }