diff options
author | Henrik Paul <henrik@vaadin.com> | 2014-03-03 11:46:35 +0200 |
---|---|---|
committer | John Ahlroos <john@vaadin.com> | 2014-03-03 09:56:47 +0000 |
commit | 3798a8ab782d5e68b269692bbb784069b9312122 (patch) | |
tree | 248e2d6317f11a6906c2c13161609c118ffff8c4 /client | |
parent | 54b448d018922f6315bb756c24c6ce7feff6e14d (diff) | |
parent | 6b7ad587042d2c98c2133c93382fb5ea8cdded8c (diff) | |
download | vaadin-framework-3798a8ab782d5e68b269692bbb784069b9312122.tar.gz vaadin-framework-3798a8ab782d5e68b269692bbb784069b9312122.zip |
Merge branch 'master' into grid
Change-Id: I2f1134ce1bd5e8dbb183881fc69120e964271245
Diffstat (limited to 'client')
30 files changed, 556 insertions, 283 deletions
diff --git a/client/src/com/vaadin/client/ApplicationConnection.java b/client/src/com/vaadin/client/ApplicationConnection.java index b84d8a376f..3d00141aae 100644 --- a/client/src/com/vaadin/client/ApplicationConnection.java +++ b/client/src/com/vaadin/client/ApplicationConnection.java @@ -65,6 +65,7 @@ import com.google.gwt.user.client.Window.ClosingHandler; import com.google.gwt.user.client.ui.HasWidgets; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.ApplicationConfiguration.ErrorMessage; +import com.vaadin.client.ApplicationConnection.ApplicationStoppedEvent; import com.vaadin.client.ResourceLoader.ResourceLoadEvent; import com.vaadin.client.ResourceLoader.ResourceLoadListener; import com.vaadin.client.communication.HasJavaScriptConnectorHelper; @@ -85,6 +86,9 @@ import com.vaadin.client.metadata.Type; import com.vaadin.client.metadata.TypeData; import com.vaadin.client.ui.AbstractComponentConnector; import com.vaadin.client.ui.AbstractConnector; +import com.vaadin.client.ui.FontIcon; +import com.vaadin.client.ui.Icon; +import com.vaadin.client.ui.ImageIcon; import com.vaadin.client.ui.VContextMenu; import com.vaadin.client.ui.VNotification; import com.vaadin.client.ui.VNotification.HideEvent; @@ -3031,6 +3035,26 @@ public class ApplicationConnection { } /** + * Gets an {@link Icon} instance corresponding to a URI. + * + * @since 7.2 + * @param uri + * @return Icon object + */ + public Icon getIcon(String uri) { + Icon icon; + if (uri == null) { + return null; + } else if (FontIcon.isFontIconUri(uri)) { + icon = GWT.create(FontIcon.class); + } else { + icon = GWT.create(ImageIcon.class); + } + icon.setUri(translateVaadinUri(uri)); + return icon; + } + + /** * Translates custom protocols in UIDL URI's to be recognizable by browser. * All uri's from UIDL should be routed via this method before giving them * to browser due URI's in UIDL may contain custom protocols like theme://. diff --git a/client/src/com/vaadin/client/Util.java b/client/src/com/vaadin/client/Util.java index edbb40e86c..7cf8338171 100644 --- a/client/src/com/vaadin/client/Util.java +++ b/client/src/com/vaadin/client/Util.java @@ -1344,7 +1344,8 @@ public class Util { divElement.getStyle().setDisplay(Display.NONE); RootPanel.getBodyElement().appendChild(divElement); - divElement.setInnerHTML("<a href='" + escapeHTML(url) + "' ></a>"); + divElement.setInnerHTML("<a href='" + escapeAttribute(url) + + "' ></a>"); AnchorElement a = divElement.getChild(0).cast(); String href = a.getHref(); diff --git a/client/src/com/vaadin/client/VCaption.java b/client/src/com/vaadin/client/VCaption.java index d96e6ed653..e11082cf47 100644 --- a/client/src/com/vaadin/client/VCaption.java +++ b/client/src/com/vaadin/client/VCaption.java @@ -24,6 +24,7 @@ import com.google.gwt.user.client.ui.HTML; import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.ui.AbstractFieldConnector; import com.vaadin.client.ui.Icon; +import com.vaadin.client.ui.ImageIcon; import com.vaadin.client.ui.aria.AriaHelper; import com.vaadin.shared.AbstractComponentState; import com.vaadin.shared.AbstractFieldState; @@ -106,6 +107,7 @@ public class VCaption extends HTML { if (null != owner) { AriaHelper.bindCaption(owner.getWidget(), getElement()); } + } @Override @@ -159,25 +161,27 @@ public class VCaption extends HTML { showRequired = ((AbstractFieldConnector) owner).isRequired(); } + if (icon != null) { + getElement().removeChild(icon.getElement()); + icon = null; + } if (hasIcon) { - if (icon == null) { - icon = new Icon(client); + String uri = owner.getState().resources.get( + ComponentConstants.ICON_RESOURCE).getURL(); + + icon = client.getIcon(uri); + + if (icon instanceof ImageIcon) { + // onload will set appropriate size later icon.setWidth("0"); icon.setHeight("0"); - - DOM.insertChild(getElement(), icon.getElement(), - getInsertPosition(InsertPosition.ICON)); } - // Icon forces the caption to be above the component - placedAfterComponent = false; - icon.setUri(owner.getState().resources.get( - ComponentConstants.ICON_RESOURCE).getURL()); + DOM.insertChild(getElement(), icon.getElement(), + getInsertPosition(InsertPosition.ICON)); - } else if (icon != null) { - // Remove existing - DOM.removeChild(getElement(), icon.getElement()); - icon = null; + // Icon forces the caption to be above the component + placedAfterComponent = false; } if (owner.getState().caption != null) { @@ -332,24 +336,24 @@ public class VCaption extends HTML { } boolean hasIcon = iconURL != null; + if (icon != null) { + getElement().removeChild(icon.getElement()); + icon = null; + } if (hasIcon) { - if (icon == null) { - icon = new Icon(client); + icon = client.getIcon(iconURL); + if (icon instanceof ImageIcon) { + // onload sets appropriate size later icon.setWidth("0"); icon.setHeight("0"); - - DOM.insertChild(getElement(), icon.getElement(), - getInsertPosition(InsertPosition.ICON)); } + icon.setAlternateText(iconAltText); + DOM.insertChild(getElement(), icon.getElement(), + getInsertPosition(InsertPosition.ICON)); + // Icon forces the caption to be above the component placedAfterComponent = false; - icon.setUri(iconURL, iconAltText); - - } else if (icon != null) { - // Remove existing - DOM.removeChild(getElement(), icon.getElement()); - icon = null; } if (caption != null) { diff --git a/client/src/com/vaadin/client/debug/internal/Icon.java b/client/src/com/vaadin/client/debug/internal/Icon.java index 9ef6d833e2..70bac11175 100644 --- a/client/src/com/vaadin/client/debug/internal/Icon.java +++ b/client/src/com/vaadin/client/debug/internal/Icon.java @@ -44,7 +44,9 @@ public enum Icon { // BAN_CIRCLE(""), // MAXIMIZE(""), // RESET(""), // - PERSIST(""); // + PERSIST(""), // + TESTBENCH(""), // + ; private String id; diff --git a/client/src/com/vaadin/client/debug/internal/TestBenchSection.java b/client/src/com/vaadin/client/debug/internal/TestBenchSection.java index 5be75f2003..b3b2d3ad86 100644 --- a/client/src/com/vaadin/client/debug/internal/TestBenchSection.java +++ b/client/src/com/vaadin/client/debug/internal/TestBenchSection.java @@ -85,7 +85,7 @@ public class TestBenchSection implements Section { } } - private final DebugButton tabButton = new DebugButton(Icon.WARNING, + private final DebugButton tabButton = new DebugButton(Icon.TESTBENCH, "Pick Vaadin TestBench selectors"); private final FlowPanel content = new FlowPanel(); diff --git a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java index 8fdaf0a5be..5933441e0a 100644 --- a/client/src/com/vaadin/client/ui/AbstractComponentConnector.java +++ b/client/src/com/vaadin/client/ui/AbstractComponentConnector.java @@ -462,15 +462,24 @@ public abstract class AbstractComponentConnector extends AbstractConnector } /** - * Gets the icon set for this component. + * Gets the URI of the icon set for this component. * - * @return the URL of the icon, or <code>null</code> if no icon has been + * @return the URI of the icon, or <code>null</code> if no icon has been * defined. */ - protected String getIcon() { + protected String getIconUri() { return getResourceUrl(ComponentConstants.ICON_RESOURCE); } + /** + * Gets the icon set for this component. + * + * @return the icon, or <code>null</code> if no icon has been defined. + */ + protected Icon getIcon() { + return getConnection().getIcon(getIconUri()); + } + /* * (non-Javadoc) * diff --git a/client/src/com/vaadin/client/ui/Action.java b/client/src/com/vaadin/client/ui/Action.java index e1b85dcb82..60d3e9aabf 100644 --- a/client/src/com/vaadin/client/ui/Action.java +++ b/client/src/com/vaadin/client/ui/Action.java @@ -17,7 +17,6 @@ package com.vaadin.client.ui; import com.google.gwt.user.client.Command; -import com.vaadin.client.Util; /** * @@ -43,9 +42,11 @@ public abstract class Action implements Command { public String getHTML() { final StringBuffer sb = new StringBuffer(); sb.append("<div>"); - if (getIconUrl() != null) { - sb.append("<img src=\"" + Util.escapeAttribute(getIconUrl()) - + "\" alt=\"icon\" />"); + // Could store the icon in a field instead, but it doesn't really matter + // right now because Actions are recreated every time they are needed + Icon icon = owner.getClient().getIcon(getIconUrl()); + if (icon != null) { + sb.append(icon.getElement().getString()); } sb.append(getCaption()); sb.append("</div>"); @@ -78,5 +79,4 @@ public abstract class Action implements Command { return "Action [owner=" + owner + ", iconUrl=" + iconUrl + ", caption=" + caption + "]"; } - } diff --git a/client/src/com/vaadin/client/ui/FontIcon.java b/client/src/com/vaadin/client/ui/FontIcon.java new file mode 100644 index 0000000000..04640fab06 --- /dev/null +++ b/client/src/com/vaadin/client/ui/FontIcon.java @@ -0,0 +1,149 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ +package com.vaadin.client.ui; + +import com.google.gwt.http.client.URL; +import com.google.gwt.user.client.DOM; +import com.vaadin.shared.ApplicationConstants; + +/** + * A font-based icon implementation. + * <p> + * The icon represents a specific character (identified by codepoint, + * {@link #getCodepoint()}, {@link #setCodepoint(int)}) within a specific font + * (identified by font-family, {@link #getFontFamily()}, + * {@link #setFontFamily(String)}). + * </p> + * + * @since 7.2 + * @author Vaadin Ltd + */ +public class FontIcon extends Icon { + + private int codepoint; + private String fontFamily; + + public FontIcon() { + setElement(DOM.createSpan()); + setStyleName(CLASSNAME); + } + + @Override + public void setUri(String uri) { + String[] parts = uri.substring( + ApplicationConstants.FONTICON_PROTOCOL_PREFIX.length()).split( + "/"); + setFontFamily(URL.decode(parts[0])); + setCodepoint(Integer.parseInt(parts[1], 16)); + } + + /** + * Not implemeted for {@link FontIcon} yet. + * + * @see com.vaadin.client.ui.Icon#setAlternateText(java.lang.String) + */ + @Override + public void setAlternateText(String alternateText) { + // TODO this is mostly for WAI-ARIA and should be implemented in an + // appropriate way. + + } + + /** + * Sets the font-family from which this icon comes. Use + * {@link #setCodepoint(int)} to specify a particular icon (character) + * within the font. + * + * @param fontFamily + * font-family name + */ + protected void setFontFamily(String fontFamily) { + if (this.fontFamily != null) { + removeStyleName(getFontStylename()); + } + this.fontFamily = fontFamily; + if (fontFamily != null) { + addStyleName(getFontStylename()); + } + } + + /** + * Gets the font-family from which this icon comes. Use + * {@link #getCodepoint()} to find out which particular icon (character) + * within the font this is. + * + * @return font-family name + */ + public String getFontFamily() { + return fontFamily; + } + + /** + * Sets the codepoint indicating which particular icon (character) within + * the font-family this is. + * + * @param codepoint + */ + protected void setCodepoint(int codepoint) { + this.codepoint = codepoint; + getElement().setInnerText(new String(Character.toChars(codepoint))); + } + + /** + * Gets the codepoint indicating which particular icon (character) within + * the font-family this is. + * + * @return + */ + public int getCodepoint() { + return codepoint; + } + + /** + * Get the font-family based stylename used to apply the font-family. + * + * @since 7.2 + * @return stylename used to apply font-family + */ + protected String getFontStylename() { + if (fontFamily == null) { + return null; + } + return fontFamily.replace(' ', '-'); + } + + /** + * Checks whether or not the given uri is a font icon uri. Does not check + * whether or not the font icon is available and can be rendered. + * + * @since 7.2 + * @param uri + * @return true if it's a fonticon uri + */ + public static boolean isFontIconUri(String uri) { + return uri != null + && uri.startsWith(ApplicationConstants.FONTICON_PROTOCOL_PREFIX); + } + + @Override + public String getUri() { + if (fontFamily == null) { + return null; + } + return ApplicationConstants.FONTICON_PROTOCOL_PREFIX + fontFamily + "/" + + codepoint; + } +} diff --git a/client/src/com/vaadin/client/ui/Icon.java b/client/src/com/vaadin/client/ui/Icon.java index 4a0e858798..219692161e 100644 --- a/client/src/com/vaadin/client/ui/Icon.java +++ b/client/src/com/vaadin/client/ui/Icon.java @@ -13,55 +13,40 @@ * License for the specific language governing permissions and limitations under * the License. */ - package com.vaadin.client.ui; -import com.google.gwt.user.client.DOM; -import com.google.gwt.user.client.Event; import com.google.gwt.user.client.ui.UIObject; import com.vaadin.client.ApplicationConnection; -public class Icon extends UIObject { - public static final String CLASSNAME = "v-icon"; - private final ApplicationConnection client; - private String myUri; - - public Icon(ApplicationConnection client) { - setElement(DOM.createImg()); - DOM.setElementProperty(getElement(), "alt", ""); - setStyleName(CLASSNAME); - this.client = client; - } - - public Icon(ApplicationConnection client, String uidlUri) { - this(client, uidlUri, ""); - } - - public Icon(ApplicationConnection client, String uidlUri, String iconAltText) { - this(client); - setUri(uidlUri, iconAltText); - } - - public void setUri(String uidlUri) { - setUri(uidlUri, ""); - } +/** + * An abstract representation of an icon. + * + * @since 7.2 + * @author Vaadin Ltd + */ +public abstract class Icon extends UIObject { - public void setUri(String uidlUri, String uidlAlt) { - if (!uidlUri.equals(myUri)) { - /* - * Start sinking onload events, widgets responsibility to react. We - * must do this BEFORE we set src as IE fires the event immediately - * if the image is found in cache (#2592). - */ - sinkEvents(Event.ONLOAD); + public static final String CLASSNAME = "v-icon"; - String uri = client.translateVaadinUri(uidlUri); - DOM.setElementProperty(getElement(), "src", uri); - myUri = uidlUri; - } + /** + * Sets the URI for the icon. The URI should be run trough + * {@link ApplicationConnection#translateVaadinUri(String)} before setting. + * <p> + * This might be a URL referencing a image (e.g {@link ImageIcon}) or a + * custom URI (e.g {@link FontIcon}). + * </p> + * + * @param uri + * the URI for this icon + */ + public abstract void setUri(String uri); - setAlternateText(uidlAlt); - } + /** + * Gets the current URI for this icon. + * + * @return URI in use + */ + public abstract String getUri(); /** * Sets the alternate text for the icon. @@ -69,8 +54,6 @@ public class Icon extends UIObject { * @param alternateText * with the alternate text. */ - public void setAlternateText(String alternateText) { - getElement().setAttribute("alt", - alternateText == null ? "" : alternateText); - } + public abstract void setAlternateText(String alternateText); + } diff --git a/client/src/com/vaadin/client/ui/ImageIcon.java b/client/src/com/vaadin/client/ui/ImageIcon.java new file mode 100644 index 0000000000..787b0175aa --- /dev/null +++ b/client/src/com/vaadin/client/ui/ImageIcon.java @@ -0,0 +1,76 @@ +/* + * Copyright 2000-2013 Vaadin Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); you may not + * use this file except in compliance with the License. You may obtain a copy of + * the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations under + * the License. + */ + +package com.vaadin.client.ui; + +import com.google.gwt.core.client.Scheduler; +import com.google.gwt.core.client.Scheduler.ScheduledCommand; +import com.google.gwt.user.client.DOM; +import com.google.gwt.user.client.Event; +import com.vaadin.client.BrowserInfo; + +/** + * A image based implementation of {@link Icon}. + * <p> + * The image is loaded from the given URL ( {@link #setUri(String)}) and + * displayed in full. + * </p> + * + * @author Vaadin Ltd + */ +public class ImageIcon extends Icon { + public static final String CLASSNAME = "v-icon"; + + public ImageIcon() { + setElement(DOM.createImg()); + setStyleName(CLASSNAME); + } + + @Override + public void setUri(final String imageUrl) { + /* + * Start sinking onload events, widgets responsibility to react. We must + * do this BEFORE we set src as IE fires the event immediately if the + * image is found in cache (#2592). + */ + sinkEvents(Event.ONLOAD); + + if (BrowserInfo.get().isIE()) { + // apply src later for IE, to ensure onload is fired + Scheduler.get().scheduleDeferred(new ScheduledCommand() { + @Override + public void execute() { + DOM.setElementProperty(getElement(), "src", imageUrl); + } + }); + } + + DOM.setElementProperty(getElement(), "src", imageUrl); + + } + + @Override + public void setAlternateText(String alternateText) { + getElement().setAttribute("alt", + alternateText == null ? "" : alternateText); + } + + @Override + public String getUri() { + return DOM.getElementProperty(getElement(), "src"); + } + +} diff --git a/client/src/com/vaadin/client/ui/VCalendarPanel.java b/client/src/com/vaadin/client/ui/VCalendarPanel.java index b043cd0ab7..5fbd3ec15c 100644 --- a/client/src/com/vaadin/client/ui/VCalendarPanel.java +++ b/client/src/com/vaadin/client/ui/VCalendarPanel.java @@ -888,9 +888,8 @@ public class VCalendarPanel extends FocusableFlexTable implements if (!isDateInsideRange(requestedNextMonthDate, Resolution.DAY)) { requestedNextMonthDate = adjustDateToFitInsideRange(requestedNextMonthDate); } - focusedDate.setYear(requestedNextMonthDate.getYear()); - focusedDate.setMonth(requestedNextMonthDate.getMonth()); - focusedDate.setDate(requestedNextMonthDate.getDate()); + + focusedDate.setTime(requestedNextMonthDate.getTime()); displayedMonth.setMonth(displayedMonth.getMonth() + 1); renderCalendar(); @@ -945,9 +944,7 @@ public class VCalendarPanel extends FocusableFlexTable implements if (!isDateInsideRange(requestedPreviousMonthDate, Resolution.DAY)) { requestedPreviousMonthDate = adjustDateToFitInsideRange(requestedPreviousMonthDate); } - focusedDate.setYear(requestedPreviousMonthDate.getYear()); - focusedDate.setMonth(requestedPreviousMonthDate.getMonth()); - focusedDate.setDate(requestedPreviousMonthDate.getDate()); + focusedDate.setTime(requestedPreviousMonthDate.getTime()); displayedMonth.setMonth(displayedMonth.getMonth() - 1); renderCalendar(); diff --git a/client/src/com/vaadin/client/ui/VFormLayout.java b/client/src/com/vaadin/client/ui/VFormLayout.java index 6c2661d1d8..56870e5e41 100644 --- a/client/src/com/vaadin/client/ui/VFormLayout.java +++ b/client/src/com/vaadin/client/ui/VFormLayout.java @@ -260,21 +260,17 @@ public class VFormLayout extends SimplePanel { boolean isEmpty = true; + if (icon != null) { + getElement().removeChild(icon.getElement()); + icon = null; + } if (state.resources.containsKey(ComponentConstants.ICON_RESOURCE)) { - if (icon == null) { - icon = new Icon(owner.getConnection()); + icon = owner.getConnection().getIcon( + state.resources.get(ComponentConstants.ICON_RESOURCE) + .getURL()); + DOM.insertChild(getElement(), icon.getElement(), 0); - DOM.insertChild(getElement(), icon.getElement(), 0); - } - icon.setUri(state.resources.get( - ComponentConstants.ICON_RESOURCE).getURL()); isEmpty = false; - } else { - if (icon != null) { - DOM.removeChild(getElement(), icon.getElement()); - icon = null; - } - } if (state.caption != null) { diff --git a/client/src/com/vaadin/client/ui/VMenuBar.java b/client/src/com/vaadin/client/ui/VMenuBar.java index 0aa26e4999..b6aee92779 100644 --- a/client/src/com/vaadin/client/ui/VMenuBar.java +++ b/client/src/com/vaadin/client/ui/VMenuBar.java @@ -226,11 +226,9 @@ public class VMenuBar extends SimpleFocusablePanel implements itemHTML.append("<span class=\"" + getStylePrimaryName() + "-menuitem-caption\">"); - if (item.hasAttribute("icon")) { - itemHTML.append("<img src=\"" - + Util.escapeAttribute(client.translateVaadinUri(item - .getStringAttribute("icon"))) + "\" class=\"" - + Icon.CLASSNAME + "\" alt=\"\" />"); + Icon icon = client.getIcon(item.getStringAttribute("icon")); + if (icon != null) { + itemHTML.append(icon.getElement().getString()); } String itemText = item.getStringAttribute("text"); if (!htmlContentAllowed) { diff --git a/client/src/com/vaadin/client/ui/VNotification.java b/client/src/com/vaadin/client/ui/VNotification.java index 128de0a285..4748df4e62 100644 --- a/client/src/com/vaadin/client/ui/VNotification.java +++ b/client/src/com/vaadin/client/ui/VNotification.java @@ -442,11 +442,9 @@ public class VNotification extends VOverlay { .hasAttribute(UIConstants.NOTIFICATION_HTML_CONTENT_NOT_ALLOWED); String html = ""; if (notification.hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON)) { - final String parsedUri = client - .translateVaadinUri(notification - .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON)); - html += "<img src=\"" + Util.escapeAttribute(parsedUri) - + "\" alt=\"\" />"; + String iconUri = notification + .getStringAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_ICON); + html += client.getIcon(iconUri).getElement().getString(); } if (notification .hasAttribute(UIConstants.ATTRIBUTE_NOTIFICATION_CAPTION)) { diff --git a/client/src/com/vaadin/client/ui/VOptionGroup.java b/client/src/com/vaadin/client/ui/VOptionGroup.java index fee1c313f5..3e4b357be3 100644 --- a/client/src/com/vaadin/client/ui/VOptionGroup.java +++ b/client/src/com/vaadin/client/ui/VOptionGroup.java @@ -139,11 +139,10 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, itemHtml = Util.escapeHTML(itemHtml); } - String icon = opUidl.getStringAttribute("icon"); - if (icon != null && icon.length() != 0) { - String iconUrl = client.translateVaadinUri(icon); - itemHtml = "<img src=\"" + iconUrl + "\" class=\"" - + Icon.CLASSNAME + "\" alt=\"\" />" + itemHtml; + String iconUrl = opUidl.getStringAttribute("icon"); + if (iconUrl != null && iconUrl.length() != 0) { + Icon icon = client.getIcon(iconUrl); + itemHtml = icon.getElement().getString() + itemHtml; } String key = opUidl.getStringAttribute("key"); @@ -160,7 +159,7 @@ public class VOptionGroup extends VOptionGroupBase implements FocusHandler, op = new RadioButton(paintableId); op.setStyleName("v-radiobutton"); } - if (icon != null && icon.length() != 0) { + if (iconUrl != null && iconUrl.length() != 0) { Util.sinkOnloadForImages(op.getElement()); op.addHandler(iconLoadHandler, LoadEvent.getType()); } diff --git a/client/src/com/vaadin/client/ui/VPanel.java b/client/src/com/vaadin/client/ui/VPanel.java index ffeacade46..32d99e7ca9 100644 --- a/client/src/com/vaadin/client/ui/VPanel.java +++ b/client/src/com/vaadin/client/ui/VPanel.java @@ -152,17 +152,12 @@ public class VPanel extends SimplePanel implements ShortcutActionHandlerOwner, /** For internal use only. May be removed or replaced in the future. */ public void setIconUri(String iconUri, ApplicationConnection client) { - if (iconUri == null) { - if (icon != null) { - DOM.removeChild(captionNode, icon.getElement()); - icon = null; - } - } else { - if (icon == null) { - icon = new Icon(client); - DOM.insertChild(captionNode, icon.getElement(), 0); - } - icon.setUri(iconUri); + if (icon != null) { + captionNode.removeChild(icon.getElement()); + } + icon = client.getIcon(iconUri); + if (icon != null) { + DOM.insertChild(captionNode, icon.getElement(), 0); } } diff --git a/client/src/com/vaadin/client/ui/VScrollTable.java b/client/src/com/vaadin/client/ui/VScrollTable.java index bbf06bfec1..1b0dd646d1 100644 --- a/client/src/com/vaadin/client/ui/VScrollTable.java +++ b/client/src/com/vaadin/client/ui/VScrollTable.java @@ -6924,10 +6924,8 @@ public class VScrollTable extends FlowPanel implements HasWidgets, String s = uidl.hasAttribute("caption") ? uidl .getStringAttribute("caption") : ""; if (uidl.hasAttribute("icon")) { - s = "<img src=\"" - + Util.escapeAttribute(client.translateVaadinUri(uidl - .getStringAttribute("icon"))) - + "\" alt=\"icon\" class=\"v-icon\">" + s; + Icon icon = client.getIcon(uidl.getStringAttribute("icon")); + s = icon.getElement().getString() + s; } return s; } diff --git a/client/src/com/vaadin/client/ui/VTextField.java b/client/src/com/vaadin/client/ui/VTextField.java index da9445c811..9360a6e172 100644 --- a/client/src/com/vaadin/client/ui/VTextField.java +++ b/client/src/com/vaadin/client/ui/VTextField.java @@ -80,6 +80,9 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, private boolean prompting = false; private int lastCursorPos = -1; + // used while checking if FF has set input prompt as value + private boolean possibleInputError = false; + public VTextField() { this(DOM.createInputText()); } @@ -88,9 +91,7 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, super(node); setStyleName(CLASSNAME); addChangeHandler(this); - if (BrowserInfo.get().isIE()) { - // IE does not send change events when pressing enter in a text - // input so we handle it using a key listener instead + if (BrowserInfo.get().isIE() || BrowserInfo.get().isFirefox()) { addKeyDownHandler(this); } addFocusHandler(this); @@ -260,6 +261,9 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, if (focusedTextField == this) { focusedTextField = null; } + if (BrowserInfo.get().isFirefox()) { + removeOnInputListener(getElement()); + } } @Override @@ -268,6 +272,11 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, if (listenTextChangeEvents) { detachCutEventListener(getElement()); } + if (BrowserInfo.get().isFirefox()) { + // Workaround for FF setting input prompt as the value if esc is + // pressed while the field is focused and empty (#8051). + addOnInputListener(getElement()); + } } /** For internal use only. May be removed or replaced in the future. */ @@ -433,8 +442,17 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, @Override public void onKeyDown(KeyDownEvent event) { - if (event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { + if (BrowserInfo.get().isIE() + && event.getNativeKeyCode() == KeyCodes.KEY_ENTER) { + // IE does not send change events when pressing enter in a text + // input so we handle it using a key listener instead valueChange(false); + } else if (BrowserInfo.get().isFirefox() + && event.getNativeKeyCode() == KeyCodes.KEY_ESCAPE + && getText().equals("")) { + // check after onInput event if inputPrompt has appeared as the + // value of the field + possibleInputError = true; } } @@ -450,4 +468,24 @@ public class VTextField extends TextBoxBase implements Field, ChangeHandler, String wrap = getElement().getAttribute("wrap"); return !"off".equals(wrap); } + + private native void addOnInputListener(Element el) + /*-{ + var self = this; + el.oninput = $entry(function() { + self.@com.vaadin.client.ui.VTextField::checkForInputError()(); + }); + }-*/; + + private native void removeOnInputListener(Element el) + /*-{ + el.oninput = null; + }-*/; + + private void checkForInputError() { + if (possibleInputError && getText().equals(inputPrompt)) { + setText(""); + } + possibleInputError = false; + } } diff --git a/client/src/com/vaadin/client/ui/VTree.java b/client/src/com/vaadin/client/ui/VTree.java index 1acd4bd05f..86c724a3e0 100644 --- a/client/src/com/vaadin/client/ui/VTree.java +++ b/client/src/com/vaadin/client/ui/VTree.java @@ -1124,23 +1124,15 @@ public class VTree extends FocusElementPanel implements VHasDropHandler, } public void setIcon(String iconUrl, String altText) { - if (iconUrl != null) { - // Add icon if not present - if (icon == null) { - icon = new Icon(client); - Roles.getImgRole().set(icon.getElement()); - DOM.insertBefore(DOM.getFirstChild(nodeCaptionDiv), - icon.getElement(), nodeCaptionSpan); - } - icon.setUri(iconUrl); - icon.getElement().setAttribute("alt", altText); - } else { - // Remove icon if present - if (icon != null) { - DOM.removeChild(DOM.getFirstChild(nodeCaptionDiv), - icon.getElement()); - icon = null; - } + if (icon != null) { + DOM.getFirstChild(nodeCaptionDiv) + .removeChild(icon.getElement()); + } + icon = client.getIcon(iconUrl); + if (icon != null) { + DOM.insertBefore(DOM.getFirstChild(nodeCaptionDiv), + icon.getElement(), nodeCaptionSpan); + icon.setAlternateText(altText); } } diff --git a/client/src/com/vaadin/client/ui/button/ButtonConnector.java b/client/src/com/vaadin/client/ui/button/ButtonConnector.java index 9a63808742..94c2841c3c 100644 --- a/client/src/com/vaadin/client/ui/button/ButtonConnector.java +++ b/client/src/com/vaadin/client/ui/button/ButtonConnector.java @@ -80,20 +80,17 @@ public class ButtonConnector extends AbstractComponentConnector implements addStateChangeHandler("resources", new StateChangeHandler() { @Override public void onStateChanged(StateChangeEvent stateChangeEvent) { - if (getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - getWidget().wrapper.insertBefore( - getWidget().icon.getElement(), - getWidget().captionElement); - } - getWidget().icon.setUri(getIcon(), getState().iconAltText); - } else { - if (getWidget().icon != null) { - getWidget().wrapper.removeChild(getWidget().icon - .getElement()); - getWidget().icon = null; - } + if (getWidget().icon != null) { + getWidget().wrapper.removeChild(getWidget().icon + .getElement()); + getWidget().icon = null; + } + Icon icon = getIcon(); + if (icon != null) { + getWidget().icon = icon; + icon.setAlternateText(getState().iconAltText); + getWidget().wrapper.insertBefore(icon.getElement(), + getWidget().captionElement); } } }); diff --git a/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java b/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java index 85e4e5ee8b..b40e96ff95 100644 --- a/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java +++ b/client/src/com/vaadin/client/ui/checkbox/CheckBoxConnector.java @@ -30,6 +30,7 @@ import com.vaadin.client.VTooltip; import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.ui.AbstractFieldConnector; import com.vaadin.client.ui.Icon; +import com.vaadin.client.ui.ImageIcon; import com.vaadin.client.ui.VCheckBox; import com.vaadin.shared.MouseEventDetails; import com.vaadin.shared.communication.FieldRpc.FocusAndBlurServerRpc; @@ -96,21 +97,17 @@ public class CheckBoxConnector extends AbstractFieldConnector implements getWidget().setEnabled(false); } - if (getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - DOM.insertChild(getWidget().getElement(), - getWidget().icon.getElement(), 1); - getWidget().icon.sinkEvents(VTooltip.TOOLTIP_EVENTS); - getWidget().icon.sinkEvents(Event.ONCLICK); - } - getWidget().icon.setUri(getIcon()); - } else if (getWidget().icon != null) { - // detach icon - DOM.removeChild(getWidget().getElement(), - getWidget().icon.getElement()); + if (getWidget().icon != null) { + getWidget().getElement().removeChild(getWidget().icon.getElement()); getWidget().icon = null; } + Icon icon = getIcon(); + if (icon != null) { + getWidget().icon = icon; + DOM.insertChild(getWidget().getElement(), icon.getElement(), 1); + icon.sinkEvents(VTooltip.TOOLTIP_EVENTS); + icon.sinkEvents(Event.ONCLICK); + } // Set text getWidget().setText(getState().caption); diff --git a/client/src/com/vaadin/client/ui/form/FormConnector.java b/client/src/com/vaadin/client/ui/form/FormConnector.java index acd0e917fc..a6015170c2 100644 --- a/client/src/com/vaadin/client/ui/form/FormConnector.java +++ b/client/src/com/vaadin/client/ui/form/FormConnector.java @@ -27,7 +27,6 @@ import com.vaadin.client.Paintable; import com.vaadin.client.TooltipInfo; import com.vaadin.client.UIDL; import com.vaadin.client.ui.AbstractComponentContainerConnector; -import com.vaadin.client.ui.Icon; import com.vaadin.client.ui.ShortcutActionHandler; import com.vaadin.client.ui.VForm; import com.vaadin.client.ui.layout.ElementResizeEvent; @@ -108,17 +107,14 @@ public class FormConnector extends AbstractComponentContainerConnector } else { getWidget().caption.setInnerText(""); } - if (getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(client); - getWidget().legend.insertFirst(getWidget().icon.getElement()); - } - getWidget().icon.setUri(getIcon()); + if (getWidget().icon != null) { + getWidget().legend.removeChild(getWidget().icon.getElement()); + } + if (getIconUri() != null) { + getWidget().icon = client.getIcon(getIconUri()); + getWidget().legend.insertFirst(getWidget().icon.getElement()); + legendEmpty = false; - } else { - if (getWidget().icon != null) { - getWidget().legend.removeChild(getWidget().icon.getElement()); - } } if (legendEmpty) { getWidget().addStyleDependentName("nocaption"); diff --git a/client/src/com/vaadin/client/ui/link/LinkConnector.java b/client/src/com/vaadin/client/ui/link/LinkConnector.java index d2c41e9f38..c8bbc426e9 100644 --- a/client/src/com/vaadin/client/ui/link/LinkConnector.java +++ b/client/src/com/vaadin/client/ui/link/LinkConnector.java @@ -87,13 +87,15 @@ public class LinkConnector extends AbstractComponentConnector { "none"); } - if (getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - getWidget().anchor.insertBefore(getWidget().icon.getElement(), - getWidget().captionElement); - } - getWidget().icon.setUri(getIcon()); + if (getWidget().icon != null) { + getWidget().anchor.removeChild(getWidget().icon.getElement()); + getWidget().icon = null; + } + Icon icon = getIcon(); + if (icon != null) { + getWidget().icon = icon; + getWidget().anchor.insertBefore(icon.getElement(), + getWidget().captionElement); } } diff --git a/client/src/com/vaadin/client/ui/menubar/MenuBarConnector.java b/client/src/com/vaadin/client/ui/menubar/MenuBarConnector.java index 3e22ebb05b..9ce418c358 100644 --- a/client/src/com/vaadin/client/ui/menubar/MenuBarConnector.java +++ b/client/src/com/vaadin/client/ui/menubar/MenuBarConnector.java @@ -27,7 +27,7 @@ import com.vaadin.client.TooltipInfo; import com.vaadin.client.UIDL; import com.vaadin.client.Util; import com.vaadin.client.ui.AbstractComponentConnector; -import com.vaadin.client.ui.Icon; +import com.vaadin.client.ui.ImageIcon; import com.vaadin.client.ui.SimpleManagedLayout; import com.vaadin.client.ui.VMenuBar; import com.vaadin.shared.ui.ComponentStateUtil; @@ -81,7 +81,7 @@ public class MenuBarConnector extends AbstractComponentConnector implements + Util.escapeAttribute(client .translateVaadinUri(moreItemUIDL .getStringAttribute("icon"))) - + "\" class=\"" + Icon.CLASSNAME + "\" alt=\"\" />"); + + "\" class=\"" + ImageIcon.CLASSNAME + "\" alt=\"\" />"); } String moreItemText = moreItemUIDL.getStringAttribute("text"); diff --git a/client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java b/client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java index 2253397b16..e4e88899eb 100644 --- a/client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java +++ b/client/src/com/vaadin/client/ui/nativebutton/NativeButtonConnector.java @@ -87,20 +87,16 @@ public class NativeButtonConnector extends AbstractComponentConnector implements getWidget().errorIndicatorElement = null; } - if (getIcon() != null) { - if (getWidget().icon == null) { - getWidget().icon = new Icon(getConnection()); - getWidget().getElement().insertBefore( - getWidget().icon.getElement(), - getWidget().captionElement); - } - getWidget().icon.setUri(getIcon(), getState().iconAltText); - } else { - if (getWidget().icon != null) { - getWidget().getElement().removeChild( - getWidget().icon.getElement()); - getWidget().icon = null; - } + if (getWidget().icon != null) { + getWidget().getElement().removeChild(getWidget().icon.getElement()); + getWidget().icon = null; + } + Icon icon = getIcon(); + if (icon != null) { + getWidget().icon = icon; + getWidget().getElement().insertBefore(icon.getElement(), + getWidget().captionElement); + icon.setAlternateText(getState().iconAltText); } } diff --git a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java index ec4307e50b..92cf83d038 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/AbstractOrderedLayoutConnector.java @@ -32,6 +32,7 @@ import com.vaadin.client.communication.StateChangeEvent; import com.vaadin.client.communication.StateChangeEvent.StateChangeHandler; import com.vaadin.client.ui.AbstractFieldConnector; import com.vaadin.client.ui.AbstractLayoutConnector; +import com.vaadin.client.ui.Icon; import com.vaadin.client.ui.LayoutClickEventHandler; import com.vaadin.client.ui.aria.AriaHelper; import com.vaadin.client.ui.layout.ElementResizeEvent; @@ -244,6 +245,8 @@ public abstract class AbstractOrderedLayoutConnector extends URLReference iconUrl = child.getState().resources .get(ComponentConstants.ICON_RESOURCE); String iconUrlString = iconUrl != null ? iconUrl.getURL() : null; + Icon icon = child.getConnection().getIcon(iconUrlString); + List<String> styles = child.getState().styles; String error = child.getState().errorMessage; boolean showError = error != null; @@ -258,8 +261,8 @@ public abstract class AbstractOrderedLayoutConnector extends } boolean enabled = child.isEnabled(); - slot.setCaption(caption, iconUrlString, styles, error, showError, - required, enabled); + slot.setCaption(caption, icon, styles, error, showError, required, + enabled); AriaHelper.handleInputRequired(child.getWidget(), required); AriaHelper.handleInputInvalid(child.getWidget(), showError); @@ -297,9 +300,9 @@ public abstract class AbstractOrderedLayoutConnector extends // remove spacing as it is exists as separate elements that cannot be // removed easily after reordering the contents - Profiler.enter("AOLC.onConnectorHierarchyChange addOrMoveSlot temporarily remove spacing"); + Profiler.enter("AOLC.onConnectorHierarchyChange temporarily remove spacing"); layout.setSpacing(false); - Profiler.leave("AOLC.onConnectorHierarchyChange addOrMoveSlot temporarily remove spacing"); + Profiler.leave("AOLC.onConnectorHierarchyChange temporarily remove spacing"); for (ComponentConnector child : getChildComponents()) { Profiler.enter("AOLC.onConnectorHierarchyChange add children"); @@ -317,12 +320,12 @@ public abstract class AbstractOrderedLayoutConnector extends } // re-add spacing for the elements that should have it - Profiler.enter("AOLC.onConnectorHierarchyChange addOrMoveSlot setSpacing"); + Profiler.enter("AOLC.onConnectorHierarchyChange setSpacing"); // spacings were removed above if (getState().spacing) { layout.setSpacing(true); } - Profiler.leave("AOLC.onConnectorHierarchyChange addOrMoveSlot setSpacing"); + Profiler.leave("AOLC.onConnectorHierarchyChange setSpacing"); for (ComponentConnector child : previousChildren) { Profiler.enter("AOLC.onConnectorHierarchyChange remove children"); @@ -332,9 +335,7 @@ public abstract class AbstractOrderedLayoutConnector extends if (slot.hasCaption()) { slot.setCaptionResizeListener(null); } - if (slot.getSpacingElement() != null) { - slot.setSpacingResizeListener(null); - } + slot.setSpacingResizeListener(null); child.removeStateChangeHandler(childStateChangeHandler); layout.removeWidget(child.getWidget()); } diff --git a/client/src/com/vaadin/client/ui/orderedlayout/Slot.java b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java index 37a97f3399..688853f6ec 100644 --- a/client/src/com/vaadin/client/ui/orderedlayout/Slot.java +++ b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java @@ -19,18 +19,21 @@ package com.vaadin.client.ui.orderedlayout; import java.util.List; import com.google.gwt.aria.client.Roles; +import com.google.gwt.core.client.GWT; import com.google.gwt.dom.client.Document; import com.google.gwt.user.client.DOM; import com.google.gwt.user.client.Element; import com.google.gwt.user.client.Event; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.SimplePanel; -import com.google.gwt.user.client.ui.UIObject; import com.google.gwt.user.client.ui.Widget; import com.vaadin.client.BrowserInfo; import com.vaadin.client.LayoutManager; import com.vaadin.client.StyleConstants; import com.vaadin.client.Util; +import com.vaadin.client.ui.FontIcon; +import com.vaadin.client.ui.Icon; +import com.vaadin.client.ui.ImageIcon; import com.vaadin.client.ui.layout.ElementResizeEvent; import com.vaadin.client.ui.layout.ElementResizeListener; import com.vaadin.shared.ui.AlignmentInfo; @@ -39,44 +42,6 @@ import com.vaadin.shared.ui.AlignmentInfo; * Represents a slot which contains the actual widget in the layout. */ public final class Slot extends SimplePanel { - /** - * The icon for each widget. Located in the caption of the slot. - */ - private static class Icon extends UIObject { - - public static final String CLASSNAME = "v-icon"; - - private String myUrl; - - /** - * Constructor - */ - public Icon() { - setElement(DOM.createImg()); - DOM.setElementProperty(getElement(), "alt", ""); - setStyleName(CLASSNAME); - } - - /** - * Set the URL where the icon is located - * - * @param url - * A fully qualified URL - */ - public void setUri(String url) { - if (!url.equals(myUrl)) { - /* - * Start sinking onload events, widgets responsibility to react. - * We must do this BEFORE we set src as IE fires the event - * immediately if the image is found in cache (#2592). - */ - sinkEvents(Event.ONLOAD); - - DOM.setElementProperty(getElement(), "src", url); - myUrl = url; - } - } - } private static final String ALIGN_CLASS_PREFIX = "v-align-"; @@ -123,15 +88,12 @@ public final class Slot extends SimplePanel { private double expandRatio = -1; /** - * Constructor + * Constructs a slot. * + * @param layout + * The layout to which this slot belongs * @param widget * The widget to put in the slot - * @param layout - * TODO - * - * @param layoutManager - * The layout manager used by the layout */ public Slot(VAbstractOrderedLayout layout, Widget widget) { this.layout = layout; @@ -165,7 +127,7 @@ public final class Slot extends SimplePanel { } /** - * Attached resize listeners to the widget, caption and spacing elements + * Attaches resize listeners to the widget, caption and spacing elements */ private void attachListeners() { if (getWidget() != null && layout.getLayoutManager() != null) { @@ -204,6 +166,8 @@ public final class Slot extends SimplePanel { lm.removeElementResizeListener(getWidget().getElement(), widgetResizeListener); } + // in many cases, the listener has already been removed by + // setSpacing(false) if (getSpacingElement() != null && spacingResizeListener != null) { lm.removeElementResizeListener(getSpacingElement(), spacingResizeListener); @@ -352,6 +316,12 @@ public final class Slot extends SimplePanel { */ getElement().getParentElement().insertBefore(spacer, getElement()); } else if (!spacing && spacer != null) { + // Remove listener before spacer to avoid memory leak + LayoutManager lm = layout.getLayoutManager(); + if (lm != null && spacingResizeListener != null) { + lm.removeElementResizeListener(spacer, spacingResizeListener); + } + spacer.removeFromParent(); spacer = null; } @@ -437,7 +407,7 @@ public final class Slot extends SimplePanel { * @param captionText * The text of the caption * @param iconUrl - * The icon URL + * The icon URL, must already be run trough translateVaadinUri() * @param styles * The style names * @param error @@ -448,10 +418,47 @@ public final class Slot extends SimplePanel { * Is the (field) required * @param enabled * Is the component enabled + * + * @deprecated Use + * {@link #setCaption(String, Icon, List, String, boolean, boolean, boolean)} + * instead */ + @Deprecated public void setCaption(String captionText, String iconUrl, List<String> styles, String error, boolean showError, boolean required, boolean enabled) { + Icon icon; + if (FontIcon.isFontIconUri(iconUrl)) { + icon = GWT.create(FontIcon.class); + } else { + icon = GWT.create(ImageIcon.class); + } + icon.setUri(iconUrl); + + setCaption(captionText, icon, styles, error, showError, required, + enabled); + } + + /** + * Set the caption of the slot + * + * @param captionText + * The text of the caption + * @param icon + * The icon + * @param styles + * The style names + * @param error + * The error message + * @param showError + * Should the error message be shown + * @param required + * Is the (field) required + * @param enabled + * Is the component enabled + */ + public void setCaption(String captionText, Icon icon, List<String> styles, + String error, boolean showError, boolean required, boolean enabled) { // TODO place for optimization: check if any of these have changed // since last time, and only run those changes @@ -461,7 +468,7 @@ public final class Slot extends SimplePanel { final Element focusedElement = Util.getFocusedElement(); // By default focus will not be lost boolean focusLost = false; - if (captionText != null || iconUrl != null || error != null || required) { + if (captionText != null || icon != null || error != null || required) { if (caption == null) { caption = DOM.createDiv(); captionWrap = DOM.createDiv(); @@ -474,7 +481,8 @@ public final class Slot extends SimplePanel { // Made changes to DOM. Focus can be lost if it was in the // widget. - focusLost = widget.getElement().isOrHasChild(focusedElement); + focusLost = (focusedElement == null ? false : widget + .getElement().isOrHasChild(focusedElement)); } } else if (caption != null) { orphan(widget); @@ -485,7 +493,8 @@ public final class Slot extends SimplePanel { captionWrap = null; // Made changes to DOM. Focus can be lost if it was in the widget. - focusLost = widget.getElement().isOrHasChild(focusedElement); + focusLost = (focusedElement == null ? false : widget.getElement() + .isOrHasChild(focusedElement)); } // Caption text @@ -506,16 +515,13 @@ public final class Slot extends SimplePanel { } // Icon - if (iconUrl != null) { - if (icon == null) { - icon = new Icon(); - caption.insertFirst(icon.getElement()); - } - icon.setUri(iconUrl); - } else if (icon != null) { + if (this.icon != null) { icon.getElement().removeFromParent(); - icon = null; } + if (icon != null) { + caption.insertFirst(icon.getElement()); + } + this.icon = icon; // Required if (required) { @@ -566,7 +572,7 @@ public final class Slot extends SimplePanel { } // Caption position - if (captionText != null || iconUrl != null) { + if (captionText != null || icon != null) { setCaptionPosition(CaptionPosition.TOP); } else { setCaptionPosition(CaptionPosition.RIGHT); diff --git a/client/src/com/vaadin/client/ui/panel/PanelConnector.java b/client/src/com/vaadin/client/ui/panel/PanelConnector.java index 4011f86c76..f2e73bae80 100644 --- a/client/src/com/vaadin/client/ui/panel/PanelConnector.java +++ b/client/src/com/vaadin/client/ui/panel/PanelConnector.java @@ -137,8 +137,8 @@ public class PanelConnector extends AbstractSingleComponentContainerConnector getWidget().client = client; getWidget().id = uidl.getId(); - if (getIcon() != null) { - getWidget().setIconUri(getIcon(), client); + if (getIconUri() != null) { + getWidget().setIconUri(getIconUri(), client); } else { getWidget().setIconUri(null, client); } diff --git a/client/src/com/vaadin/client/ui/upload/UploadConnector.java b/client/src/com/vaadin/client/ui/upload/UploadConnector.java index 989a913adc..03f1a2802c 100644 --- a/client/src/com/vaadin/client/ui/upload/UploadConnector.java +++ b/client/src/com/vaadin/client/ui/upload/UploadConnector.java @@ -16,13 +16,17 @@ package com.vaadin.client.ui.upload; +import com.google.gwt.event.dom.client.ChangeEvent; +import com.google.gwt.event.dom.client.ChangeHandler; import com.vaadin.client.ApplicationConnection; import com.vaadin.client.Paintable; import com.vaadin.client.UIDL; import com.vaadin.client.ui.AbstractComponentConnector; import com.vaadin.client.ui.VUpload; +import com.vaadin.shared.EventId; import com.vaadin.shared.ui.Connect; import com.vaadin.shared.ui.upload.UploadClientRpc; +import com.vaadin.shared.ui.upload.UploadServerRpc; import com.vaadin.ui.Upload; @Connect(Upload.class) @@ -39,6 +43,21 @@ public class UploadConnector extends AbstractComponentConnector implements } @Override + protected void init() { + super.init(); + + getWidget().fu.addChangeHandler(new ChangeHandler() { + @Override + public void onChange(ChangeEvent event) { + if (hasEventListener(EventId.CHANGE)) { + getRpcProxy(UploadServerRpc.class).change( + getWidget().fu.getFilename()); + } + } + }); + } + + @Override public void updateFromUIDL(UIDL uidl, ApplicationConnection client) { if (!isRealUpdate(uidl)) { return; diff --git a/client/src/com/vaadin/client/ui/window/WindowConnector.java b/client/src/com/vaadin/client/ui/window/WindowConnector.java index 788799d81c..b6fe541c00 100644 --- a/client/src/com/vaadin/client/ui/window/WindowConnector.java +++ b/client/src/com/vaadin/client/ui/window/WindowConnector.java @@ -295,8 +295,8 @@ public class WindowConnector extends AbstractSingleComponentContainerConnector // Caption must be set before required header size is measured. If // the caption attribute is missing the caption should be cleared. String iconURL = null; - if (getIcon() != null) { - iconURL = getIcon(); + if (getIconUri() != null) { + iconURL = getIconUri(); } window.setAssistivePrefix(state.assistivePrefix); |