Fixes race condition in RichTextAreaImplIE6, and badly borked Opera implementation. Patch by: jgw Review by: rdayal git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@1103 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/user/src/com/google/gwt/user/client/ui/RichTextArea.java b/user/src/com/google/gwt/user/client/ui/RichTextArea.java index c62f15d..cac8406 100644 --- a/user/src/com/google/gwt/user/client/ui/RichTextArea.java +++ b/user/src/com/google/gwt/user/client/ui/RichTextArea.java
@@ -25,8 +25,8 @@ * * Because some browsers do not support rich text editing, and others support * only a limited subset of functionality, there are two formatter interfaces, - * accessed via {@link #getBasicFormatter()} and {@link #getExtendedFormatter()}. A - * browser that does not support rich text editing at all will return + * accessed via {@link #getBasicFormatter()} and {@link #getExtendedFormatter()}. + * A browser that does not support rich text editing at all will return * <code>null</code> for both of these, while one that supports only the basic * functionality will return <code>null</code> for the latter. * @@ -40,7 +40,7 @@ * </ul> */ public class RichTextArea extends FocusWidget implements HasHTML, - SourcesMouseEvents, SourcesChangeEvents { + SourcesMouseEvents { /** * This interface is used to access basic formatting options, when available. @@ -325,7 +325,6 @@ } private RichTextAreaImpl impl = (RichTextAreaImpl) GWT.create(RichTextAreaImpl.class); - private ChangeListenerCollection changeListeners; private MouseListenerCollection mouseListeners; /** @@ -336,13 +335,6 @@ setStyleName("gwt-RichTextArea"); } - public void addChangeListener(ChangeListener listener) { - if (changeListeners == null) { - changeListeners = new ChangeListenerCollection(); - } - changeListeners.add(listener); - } - public void addMouseListener(MouseListener listener) { if (mouseListeners == null) { mouseListeners = new MouseListenerCollection(); @@ -395,25 +387,12 @@ } break; - case Event.ONCHANGE: - // TODO: there's no code to fire this on IE6. - if (changeListeners != null) { - changeListeners.fireChange(this); - } - break; - default: // ClickEvents and KeyboardEvents super.onBrowserEvent(event); } } - public void removeChangeListener(ChangeListener listener) { - if (changeListeners != null) { - changeListeners.remove(listener); - } - } - public void removeMouseListener(MouseListener listener) { if (mouseListeners != null) { mouseListeners.remove(listener);
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java index 85e1d9d..0b8ce57 100644 --- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java +++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplIE6.java
@@ -17,14 +17,14 @@ import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; -import com.google.gwt.user.client.ui.RichTextArea; /** * IE6-specific implementation of rich-text editing. */ public class RichTextAreaImplIE6 extends RichTextAreaImplStandard { - private static native void attachEvents(Element elem) /*-{ + native void initEvents() /*-{ + var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; var handler = function() { if (elem.__listener) { // Weird: this code has the context of the script frame, but we need the @@ -33,7 +33,7 @@ elem.__listener.@com.google.gwt.user.client.ui.RichTextArea::onBrowserEvent(Lcom/google/gwt/user/client/Event;)(evt); } }; - + var body = elem.contentWindow.document.body; body.onkeydown = body.onkeyup = @@ -63,13 +63,6 @@ return elem.contentWindow.document.body.innerText; }-*/; - private static native void writeHtml(Element elem) /*-{ - var doc = elem.contentWindow.document; - doc.open(); - doc.write('<html><body CONTENTEDITABLE="true"></body></html>'); - doc.close(); - }-*/; - public Element createElement() { Element elem = super.createElement(); DOM.setElementProperty(elem, "src", "javascript:''"); @@ -80,14 +73,20 @@ return getText(elem); } - public void hookEvents(RichTextArea owner) { - attachEvents(elem); - super.hookEvents(owner); - } + public native void initElement() /*-{ + var elem = this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem; + var _this = this; - public void initElement() { - writeHtml(elem); - } + window.setTimeout(function() { + var doc = elem.contentWindow.document; + doc.open(); + doc.write('<html><body CONTENTEDITABLE="true"></body></html>'); + doc.close(); + + // Initialize event handling. + _this.@com.google.gwt.user.client.ui.impl.RichTextAreaImplIE6::initEvents()(); + }, 1); + }-*/; public void unhookEvents() { super.unhookEvents();
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplOpera.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplOpera.java index 65587ec..5d3fef0 100644 --- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplOpera.java +++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplOpera.java
@@ -15,7 +15,6 @@ */ package com.google.gwt.user.client.ui.impl; -import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.ui.RichTextArea; @@ -24,66 +23,71 @@ */ public class RichTextAreaImplOpera extends RichTextAreaImplStandard { - private static boolean supportsEditing; + private static boolean richTextSupported = detectEditingSupport(); + private static RichTextAreaImpl old; + + static { + // If rich text is not supported by this version of Opera, create an + // instance of the default impl and shunt all calls to it. + if (!richTextSupported) { + old = new RichTextAreaImpl(); + } + } + + private static native boolean detectEditingSupport() /*-{ + return !!$doc.designMode; + }-*/; public Element createElement() { - supportsEditing = detectEditingSupport(); - if (supportsEditing) { - return super.createElement(); + if (old != null) { + return old.createElement(); } - return DOM.createTextArea(); + return super.createElement(); + } + + public Element getElement() { + if (old != null) { + return old.getElement(); + } + return super.getElement(); } public String getHTML() { - if (supportsEditing) { - return super.getHTML(); + if (old != null) { + return old.getHTML(); } - - // THIS DOESN'T WORK, unless there's a compiler bug! - return ((RichTextAreaImpl) this).getHTML(); + return super.getHTML(); } public String getText() { - if (supportsEditing) { - return super.getText(); + if (old != null) { + return old.getText(); } - - // THIS DOESN'T WORK, unless there's a compiler bug! - return ((RichTextAreaImpl) this).getText(); + return super.getText(); } public void hookEvents(RichTextArea owner) { - if (supportsEditing) { - super.hookEvents(owner); + if (old != null) { + old.hookEvents(owner); return; } - - // THIS DOESN'T WORK, unless there's a compiler bug! - ((RichTextAreaImpl) this).hookEvents(owner); + super.hookEvents(owner); } public void initElement() { - if (supportsEditing) { - super.initElement(); + if (old != null) { + old.initElement(); return; } - - // THIS DOESN'T WORK, unless there's a compiler bug! - ((RichTextAreaImpl) this).initElement(); + super.initElement(); } public boolean isBasicEditingSupported() { - return supportsEditing; + return richTextSupported; } - public boolean isFullEditingSupported() { - return supportsEditing; - } - - public void setBackColor(String color) { - // Opera uses 'BackColor' for the *entire area's* background. 'HiliteColor' - // does what we actually want. - execCommand("HiliteColor", color); + public boolean isExtendedEditingSupported() { + return richTextSupported; } public native void setFocus(boolean focused) /*-{ @@ -96,57 +100,31 @@ }-*/; public void setHTML(String html) { - if (supportsEditing) { - super.setHTML(html); + if (old != null) { + old.setHTML(html); + return; } - - // Unsupported fallback. - DOM.setElementProperty(elem, "value", html); + super.setHTML(html); } public void setText(String text) { - if (supportsEditing) { - super.setText(text); + if (old != null) { + old.setText(text); + return; } - - // Unsupported fallback. - DOM.setElementProperty(elem, "value", text); + super.setText(text); } public void unhookEvents() { - if (supportsEditing) { - super.unhookEvents(); - return; + if (old != null) { + old.unhookEvents(); } - - // THIS DOESN'T WORK, unless there's a compiler bug! - ((RichTextAreaImpl) this).unhookEvents(); + super.unhookEvents(); } - void execCommand(String cmd, String param) { - if (isRichEditingActive(elem)) { - // Opera doesn't need focus for execCommand() to work, but focusing - // the editor causes it to lose its selection, so we focus *after* - // execCommand(). - execCommandAssumingFocus(cmd, param); - setFocus(true); - - // TODO: Opera has now lost its selection. Figure out a way to restore it - // reliably. - } + public void setBackColor(String color) { + // Opera uses 'BackColor' for the *entire area's* background. 'HiliteColor' + // does what we actually want. + execCommand("HiliteColor", color); } - - boolean queryCommandState(String cmd) { - // Opera doesn't need focus (and setting it dumps selection). - return queryCommandStateAssumingFocus(cmd); - } - - String queryCommandValue(String cmd) { - // Opera doesn't need focus (and setting it dumps selection). - return queryCommandValueAssumingFocus(cmd); - } - - private native boolean detectEditingSupport() /*-{ - return !!$doc.designMode; - }-*/; }
diff --git a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplSafari.java b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplSafari.java index 5569548..bc7695d 100644 --- a/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplSafari.java +++ b/user/src/com/google/gwt/user/client/ui/impl/RichTextAreaImplSafari.java
@@ -54,7 +54,7 @@ }-*/; public native void setFocus(boolean focused) /*-{ - // Opera needs the *iframe* focused, not its window. + // Safari needs the *iframe* focused, not its window. if (focused) { this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.focus(); this.@com.google.gwt.user.client.ui.impl.RichTextAreaImpl::elem.__gwt_restoreSelection();