From: Marc Englund Date: Tue, 11 Feb 2014 08:15:07 +0000 (+0200) Subject: Font icon support (#13152) X-Git-Tag: 7.2.0.beta1~154 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=de70ee2f0132661c9bf771cb66a40d1961073037;p=vaadin-framework.git Font icon support (#13152) Renamed Icon to ImageIcon Change-Id: I608815f17a3651b205fed81b5294385df0d68802 Extracted the abstract client-side Icon class Change-Id: Ic32e270595a5796d0bbd1dd31f34282b56672aa9 Created the FontIcon class Change-Id: Iad13871e7bf1807dee2c538c76306d4620191f5e Renamed AbstractComponentConnector.getIcon to getIconUri Change-Id: I6953ab79661993b561655d483c1bd013b66407f3 Added the AbstractComponentConnector.getIcon method Change-Id: I6fb91dc643fb09da3ba53666b1a8a289901702e3 Refactored getIcon Change-Id: Ibae39e66d0fb8449e20ac5209eb8c18b6ada4387 Made all existing uses of Icon compatible with FontIcons Change-Id: I8f28ec5254f2e5282a887519d3f44bc1e27aba72 Initial server-side support for font icons - does not include an actual icon set yet (#13152) Change-Id: Ie6c09b17dd577c726e0efc13567749f6f4d56d8d Changed server side FontIcon URI generation to match the correct scheme Change-Id: I3628b930b310b3f285bc58a3f471e31e641d307e Initial server-side icon font (FontAwesome) with scss - to be considered placeholder for testing (#13152) Change-Id: I361e62aba0d943a736471824e149d65c7eea9c76 Changed the FontIcon URI scheme Change-Id: I15c92f6bb3d0aa0a800f3f0bfa80419979453e17 Added FontIcon support to AbstractOrderedLayoutConnector Change-Id: I3b2b45b22d29622fd888dbe922aa0cc8a718104d Added FontIcon support to table items Change-Id: Id22ce94c96a892420aab1e39663688fc9f3bc282 Added FontIcon support to OptionGroup items Change-Id: Ie08bef688f6802182ef5f8b2bf82cf8b1f9096bb Switched to openly use FontAwesome (#13152) Change-Id: I18c3325ce93915b7fd6e338c8c293a89711277bc VaadinIcons are now FontAwesome (#13152) Change-Id: I0ab2a80735cbf08b6e33d358e3e8c6a205626fc4 VCaption does not longer set icon to 0x0px if it's a FontIcon (#13152) Change-Id: Ibcd96e0f79f0adf2e217a8580d17f1cc93705710 Fixed typo in @font-face, removed .otf (#13152) Change-Id: I698ca32c560e5f198c32a6c44f7884d3030ee610 Make font icons behave more like img (display:inline-block) (#13152) Change-Id: Ic79186c90f1fc566deae1f4d8d4ba2c21d89a42e --- diff --git a/WebContent/VAADIN/themes/base/base.scss b/WebContent/VAADIN/themes/base/base.scss index aa1e778d6f..fd3c5d067d 100644 --- a/WebContent/VAADIN/themes/base/base.scss +++ b/WebContent/VAADIN/themes/base/base.scss @@ -15,6 +15,7 @@ @import "inlinedatefield/inlinedatefield.scss"; @import "dragwrapper/dragwrapper.scss"; @import "embedded/embedded.scss"; +@import "fonts/fonts.scss"; @import "formlayout/formlayout.scss"; @import "gridlayout/gridlayout.scss"; @import "label/label.scss"; @@ -119,3 +120,4 @@ $line-height: normal; // always include, don't wrap in .themename{} @include debug-globals; +@include fonts; diff --git a/WebContent/VAADIN/themes/base/common/common.scss b/WebContent/VAADIN/themes/base/common/common.scss index 5cae1b26ce..6ec85e3c6d 100644 --- a/WebContent/VAADIN/themes/base/common/common.scss +++ b/WebContent/VAADIN/themes/base/common/common.scss @@ -243,6 +243,7 @@ input::-ms-clear { width: 0; height: 0; } + } /* Outside the base mixin because elements might be added directly to the body */ diff --git a/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.eot b/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.eot new file mode 100644 index 0000000000..7c79c6a6bc Binary files /dev/null and b/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.eot differ diff --git a/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.svg b/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.svg new file mode 100644 index 0000000000..45fdf33830 --- /dev/null +++ b/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.svg @@ -0,0 +1,414 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.ttf b/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.ttf new file mode 100644 index 0000000000..e89738de5e Binary files /dev/null and b/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.ttf differ diff --git a/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.woff b/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.woff new file mode 100644 index 0000000000..8c1748aab7 Binary files /dev/null and b/WebContent/VAADIN/themes/base/fonts/fontawesome-webfont.woff differ diff --git a/WebContent/VAADIN/themes/base/fonts/fonts.scss b/WebContent/VAADIN/themes/base/fonts/fonts.scss new file mode 100644 index 0000000000..2a882ab53d --- /dev/null +++ b/WebContent/VAADIN/themes/base/fonts/fonts.scss @@ -0,0 +1,25 @@ +@mixin fonts { + @include fonticons; +} + +@mixin fonticons { + @include font(FontAwesome, fontawesome-webfont); +} + +@mixin font($font-family, $file-name) { + @font-face { + font-family: '#{$font-family}'; + src: url('#{$file-name}.eot'); + src: url('#{$file-name}.eot?#iefix') format('embedded-opentype'), url('#{$file-name}.woff') format('woff'), url('#{$file-name}.ttf') format('truetype'), url('#{$file-name}.svg') format('svg'); + font-weight: normal; + font-style: normal; + } + .#{$font-family} { + font-family: '#{$font-family}'; + font-style: normal; + font-weight: normal; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + display: inline-block; + } +} diff --git a/WebContent/license.html b/WebContent/license.html index 5e9bfe4dc5..0f9a573041 100644 --- a/WebContent/license.html +++ b/WebContent/license.html @@ -130,7 +130,11 @@ jQuery^ The MIT License - + + + FontAwesome + SIL OFL 1.1 + diff --git a/WebContent/licenses/OFL.txt b/WebContent/licenses/OFL.txt new file mode 100644 index 0000000000..f1a20ac1a8 --- /dev/null +++ b/WebContent/licenses/OFL.txt @@ -0,0 +1,97 @@ +Copyright (c) , (), +with Reserved Font Name . +Copyright (c) , (), +with Reserved Font Name . +Copyright (c) , (). + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. 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; @@ -3030,6 +3034,26 @@ public class ApplicationConnection { return contextMenu; } + /** + * 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 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/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 null if no icon has been + * @return the URI of the icon, or null 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 null if no icon has been defined. + */ + protected Icon getIcon() { + return getConnection().getIcon(getIconUri()); + } + /* * (non-Javadoc) * 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. + *

+ * 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)}). + *

+ * + * @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. + *

+ * This might be a URL referencing a image (e.g {@link ImageIcon}) or a + * custom URI (e.g {@link FontIcon}). + *

+ * + * @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}. + *

+ * The image is loaded from the given URL ( {@link #setUri(String)}) and + * displayed in full. + *

+ * + * @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/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..6c994777a7 100644 --- a/client/src/com/vaadin/client/ui/VMenuBar.java +++ b/client/src/com/vaadin/client/ui/VMenuBar.java @@ -230,7 +230,7 @@ public class VMenuBar extends SimpleFocusablePanel implements itemHTML.append("\"\""); + + ImageIcon.CLASSNAME + "\" alt=\"\" />"); } String itemText = item.getStringAttribute("text"); if (!htmlContentAllowed) { diff --git a/client/src/com/vaadin/client/ui/VOptionGroup.java b/client/src/com/vaadin/client/ui/VOptionGroup.java index fe4ef214cb..3e4b357be3 100644 --- a/client/src/com/vaadin/client/ui/VOptionGroup.java +++ b/client/src/com/vaadin/client/ui/VOptionGroup.java @@ -139,12 +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 = "\"\"" - + 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"); @@ -161,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 = "\"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/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..166e4b7530 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 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); diff --git a/client/src/com/vaadin/client/ui/orderedlayout/Slot.java b/client/src/com/vaadin/client/ui/orderedlayout/Slot.java index efa19895a8..6e1e8d28eb 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; @@ -437,7 +399,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 +410,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 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 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 +460,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(); @@ -508,16 +507,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) { @@ -568,7 +564,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/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); diff --git a/server/src/com/vaadin/server/FontAwesome.java b/server/src/com/vaadin/server/FontAwesome.java new file mode 100644 index 0000000000..a7f4c7b342 --- /dev/null +++ b/server/src/com/vaadin/server/FontAwesome.java @@ -0,0 +1,447 @@ +/* + * Copyright 2000-2014 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.server; + +/** + * FontAwesome set of font icons. + *

+ * Each {@link FontIcon} comes from the FontAwesome font family, which is + * included in the theme.
+ * Consider this a starting point: it is unlikely an application needs exactly + * these icons, and all of them, so you might want to consider making a custom + * icon font - either to get other icons, or to minimize the size of the font. + *

+ * + * @since 7.2 + * @author Vaadin Ltd + * @see http://fortawesome.github.io/Font-Awesome/ + */ +public enum FontAwesome implements FontIcon { + GLASS(0XF000), // + MUSIC(0XF001), // + SEARCH(0XF002), // + ENVELOPE_O(0XF003), // + HEART(0XF004), // + STAR(0XF005), // + STAR_O(0XF006), // + USER(0XF007), // + FILM(0XF008), // + TH_LARGE(0XF009), // + TH(0XF00A), // + TH_LIST(0XF00B), // + CHECK(0XF00C), // + TIMES(0XF00D), // + SEARCH_PLUS(0XF00E), // + SEARCH_MINUS(0XF010), // + POWER_OFF(0XF011), // + SIGNAL(0XF012), // + COG(0XF013), // + TRASH_O(0XF014), // + HOME(0XF015), // + FILE_O(0XF016), // + CLOCK_O(0XF017), // + ROAD(0XF018), // + DOWNLOAD(0XF019), // + ARROW_CIRCLE_O_DOWN(0XF01A), // + ARROW_CIRCLE_O_UP(0XF01B), // + INBOX(0XF01C), // + PLAY_CIRCLE_O(0XF01D), // + REPEAT(0XF01E), // + REFRESH(0XF021), // + LIST_ALT(0XF022), // + LOCK(0XF023), // + FLAG(0XF024), // + HEADPHONES(0XF025), // + VOLUME_OFF(0XF026), // + VOLUME_DOWN(0XF027), // + VOLUME_UP(0XF028), // + QRCODE(0XF029), // + BARCODE(0XF02A), // + TAG(0XF02B), // + TAGS(0XF02C), // + BOOK(0XF02D), // + BOOKMARK(0XF02E), // + PRINT(0XF02F), // + CAMERA(0XF030), // + FONT(0XF031), // + BOLD(0XF032), // + ITALIC(0XF033), // + TEXT_HEIGHT(0XF034), // + TEXT_WIDTH(0XF035), // + ALIGN_LEFT(0XF036), // + ALIGN_CENTER(0XF037), // + ALIGN_RIGHT(0XF038), // + ALIGN_JUSTIFY(0XF039), // + LIST(0XF03A), // + OUTDENT(0XF03B), // + INDENT(0XF03C), // + VIDEO_CAMERA(0XF03D), // + PICTURE_O(0XF03E), // + PENCIL(0XF040), // + MAP_MARKER(0XF041), // + ADJUST(0XF042), // + TINT(0XF043), // + PENCIL_SQUARE_O(0XF044), // + SHARE_SQUARE_O(0XF045), // + CHECK_SQUARE_O(0XF046), // + ARROWS(0XF047), // + STEP_BACKWARD(0XF048), // + FAST_BACKWARD(0XF049), // + BACKWARD(0XF04A), // + PLAY(0XF04B), // + PAUSE(0XF04C), // + STOP(0XF04D), // + FORWARD(0XF04E), // + FAST_FORWARD(0XF050), // + STEP_FORWARD(0XF051), // + EJECT(0XF052), // + CHEVRON_LEFT(0XF053), // + CHEVRON_RIGHT(0XF054), // + PLUS_CIRCLE(0XF055), // + MINUS_CIRCLE(0XF056), // + TIMES_CIRCLE(0XF057), // + CHECK_CIRCLE(0XF058), // + QUESTION_CIRCLE(0XF059), // + INFO_CIRCLE(0XF05A), // + CROSSHAIRS(0XF05B), // + TIMES_CIRCLE_O(0XF05C), // + CHECK_CIRCLE_O(0XF05D), // + BAN(0XF05E), // + ARROW_LEFT(0XF060), // + ARROW_RIGHT(0XF061), // + ARROW_UP(0XF062), // + ARROW_DOWN(0XF063), // + SHARE(0XF064), // + EXPAND(0XF065), // + COMPRESS(0XF066), // + PLUS(0XF067), // + MINUS(0XF068), // + ASTERISK(0XF069), // + EXCLAMATION_CIRCLE(0XF06A), // + GIFT(0XF06B), // + LEAF(0XF06C), // + FIRE(0XF06D), // + EYE(0XF06E), // + EYE_SLASH(0XF070), // + EXCLAMATION_TRIANGLE(0XF071), // + PLANE(0XF072), // + CALENDAR(0XF073), // + RANDOM(0XF074), // + COMMENT(0XF075), // + MAGNET(0XF076), // + CHEVRON_UP(0XF077), // + CHEVRON_DOWN(0XF078), // + RETWEET(0XF079), // + SHOPPING_CART(0XF07A), // + FOLDER(0XF07B), // + FOLDER_OPEN(0XF07C), // + ARROWS_V(0XF07D), // + ARROWS_H(0XF07E), // + BAR_CHART_O(0XF080), // + TWITTER_SQUARE(0XF081), // + FACEBOOK_SQUARE(0XF082), // + CAMERA_RETRO(0XF083), // + KEY(0XF084), // + COGS(0XF085), // + COMMENTS(0XF086), // + THUMBS_O_UP(0XF087), // + THUMBS_O_DOWN(0XF088), // + STAR_HALF(0XF089), // + HEART_O(0XF08A), // + SIGN_OUT(0XF08B), // + LINKEDIN_SQUARE(0XF08C), // + THUMB_TACK(0XF08D), // + EXTERNAL_LINK(0XF08E), // + SIGN_IN(0XF090), // + TROPHY(0XF091), // + GITHUB_SQUARE(0XF092), // + UPLOAD(0XF093), // + LEMON_O(0XF094), // + PHONE(0XF095), // + SQUARE_O(0XF096), // + BOOKMARK_O(0XF097), // + PHONE_SQUARE(0XF098), // + TWITTER(0XF099), // + FACEBOOK(0XF09A), // + GITHUB(0XF09B), // + UNLOCK(0XF09C), // + CREDIT_CARD(0XF09D), // + RSS(0XF09E), // + HDD_O(0XF0A0), // + BULLHORN(0XF0A1), // + BELL(0XF0F3), // + CERTIFICATE(0XF0A3), // + HAND_O_RIGHT(0XF0A4), // + HAND_O_LEFT(0XF0A5), // + HAND_O_UP(0XF0A6), // + HAND_O_DOWN(0XF0A7), // + ARROW_CIRCLE_LEFT(0XF0A8), // + ARROW_CIRCLE_RIGHT(0XF0A9), // + ARROW_CIRCLE_UP(0XF0AA), // + ARROW_CIRCLE_DOWN(0XF0AB), // + GLOBE(0XF0AC), // + WRENCH(0XF0AD), // + TASKS(0XF0AE), // + FILTER(0XF0B0), // + BRIEFCASE(0XF0B1), // + ARROWS_ALT(0XF0B2), // + USERS(0XF0C0), // + LINK(0XF0C1), // + CLOUD(0XF0C2), // + FLASK(0XF0C3), // + SCISSORS(0XF0C4), // + FILES_O(0XF0C5), // + PAPERCLIP(0XF0C6), // + FLOPPY_O(0XF0C7), // + SQUARE(0XF0C8), // + BARS(0XF0C9), // + LIST_UL(0XF0CA), // + LIST_OL(0XF0CB), // + STRIKETHROUGH(0XF0CC), // + UNDERLINE(0XF0CD), // + TABLE(0XF0CE), // + MAGIC(0XF0D0), // + TRUCK(0XF0D1), // + PINTEREST(0XF0D2), // + PINTEREST_SQUARE(0XF0D3), // + GOOGLE_PLUS_SQUARE(0XF0D4), // + GOOGLE_PLUS(0XF0D5), // + MONEY(0XF0D6), // + CARET_DOWN(0XF0D7), // + CARET_UP(0XF0D8), // + CARET_LEFT(0XF0D9), // + CARET_RIGHT(0XF0DA), // + COLUMNS(0XF0DB), // + SORT(0XF0DC), // + SORT_ASC(0XF0DD), // + SORT_DESC(0XF0DE), // + ENVELOPE(0XF0E0), // + LINKEDIN(0XF0E1), // + UNDO(0XF0E2), // + GAVEL(0XF0E3), // + TACHOMETER(0XF0E4), // + COMMENT_O(0XF0E5), // + COMMENTS_O(0XF0E6), // + BOLT(0XF0E7), // + SITEMAP(0XF0E8), // + UMBRELLA(0XF0E9), // + CLIPBOARD(0XF0EA), // + LIGHTBULB_O(0XF0EB), // + EXCHANGE(0XF0EC), // + CLOUD_DOWNLOAD(0XF0ED), // + CLOUD_UPLOAD(0XF0EE), // + USER_MD(0XF0F0), // + STETHOSCOPE(0XF0F1), // + SUITCASE(0XF0F2), // + BELL_O(0XF0A2), // + COFFEE(0XF0F4), // + CUTLERY(0XF0F5), // + FILE_TEXT_O(0XF0F6), // + BUILDING_O(0XF0F7), // + HOSPITAL_O(0XF0F8), // + AMBULANCE(0XF0F9), // + MEDKIT(0XF0FA), // + FIGHTER_JET(0XF0FB), // + BEER(0XF0FC), // + H_SQUARE(0XF0FD), // + PLUS_SQUARE(0XF0FE), // + ANGLE_DOUBLE_LEFT(0XF100), // + ANGLE_DOUBLE_RIGHT(0XF101), // + ANGLE_DOUBLE_UP(0XF102), // + ANGLE_DOUBLE_DOWN(0XF103), // + ANGLE_LEFT(0XF104), // + ANGLE_RIGHT(0XF105), // + ANGLE_UP(0XF106), // + ANGLE_DOWN(0XF107), // + DESKTOP(0XF108), // + LAPTOP(0XF109), // + TABLET(0XF10A), // + MOBILE(0XF10B), // + CIRCLE_O(0XF10C), // + QUOTE_LEFT(0XF10D), // + QUOTE_RIGHT(0XF10E), // + SPINNER(0XF110), // + CIRCLE(0XF111), // + REPLY(0XF112), // + GITHUB_ALT(0XF113), // + FOLDER_O(0XF114), // + FOLDER_OPEN_O(0XF115), // + SMILE_O(0XF118), // + FROWN_O(0XF119), // + MEH_O(0XF11A), // + GAMEPAD(0XF11B), // + KEYBOARD_O(0XF11C), // + FLAG_O(0XF11D), // + FLAG_CHECKERED(0XF11E), // + TERMINAL(0XF120), // + CODE(0XF121), // + REPLY_ALL(0XF122), // + MAIL_REPLY_ALL(0XF122), // + STAR_HALF_O(0XF123), // + LOCATION_ARROW(0XF124), // + CROP(0XF125), // + CODE_FORK(0XF126), // + CHAIN_BROKEN(0XF127), // + QUESTION(0XF128), // + INFO(0XF129), // + EXCLAMATION(0XF12A), // + SUPERSCRIPT(0XF12B), // + SUBSCRIPT(0XF12C), // + ERASER(0XF12D), // + PUZZLE_PIECE(0XF12E), // + MICROPHONE(0XF130), // + MICROPHONE_SLASH(0XF131), // + SHIELD(0XF132), // + CALENDAR_O(0XF133), // + FIRE_EXTINGUISHER(0XF134), // + ROCKET(0XF135), // + MAXCDN(0XF136), // + CHEVRON_CIRCLE_LEFT(0XF137), // + CHEVRON_CIRCLE_RIGHT(0XF138), // + CHEVRON_CIRCLE_UP(0XF139), // + CHEVRON_CIRCLE_DOWN(0XF13A), // + HTML5(0XF13B), // + CSS3(0XF13C), // + ANCHOR(0XF13D), // + UNLOCK_ALT(0XF13E), // + BULLSEYE(0XF140), // + ELLIPSIS_H(0XF141), // + ELLIPSIS_V(0XF142), // + RSS_SQUARE(0XF143), // + PLAY_CIRCLE(0XF144), // + TICKET(0XF145), // + MINUS_SQUARE(0XF146), // + MINUS_SQUARE_O(0XF147), // + LEVEL_UP(0XF148), // + LEVEL_DOWN(0XF149), // + CHECK_SQUARE(0XF14A), // + PENCIL_SQUARE(0XF14B), // + EXTERNAL_LINK_SQUARE(0XF14C), // + SHARE_SQUARE(0XF14D), // + COMPASS(0XF14E), // + CARET_SQUARE_O_DOWN(0XF150), // + CARET_SQUARE_O_UP(0XF151), // + CARET_SQUARE_O_RIGHT(0XF152), // + EUR(0XF153), // + GBP(0XF154), // + USD(0XF155), // + INR(0XF156), // + JPY(0XF157), // + RUB(0XF158), // + KRW(0XF159), // + BTC(0XF15A), // + FILE(0XF15B), // + FILE_TEXT(0XF15C), // + SORT_ALPHA_ASC(0XF15D), // + SORT_ALPHA_DESC(0XF15E), // + SORT_AMOUNT_ASC(0XF160), // + SORT_AMOUNT_DESC(0XF161), // + SORT_NUMERIC_ASC(0XF162), // + SORT_NUMERIC_DESC(0XF163), // + THUMBS_UP(0XF164), // + THUMBS_DOWN(0XF165), // + YOUTUBE_SQUARE(0XF166), // + YOUTUBE(0XF167), // + XING(0XF168), // + XING_SQUARE(0XF169), // + YOUTUBE_PLAY(0XF16A), // + DROPBOX(0XF16B), // + STACK_OVERFLOW(0XF16C), // + INSTAGRAM(0XF16D), // + FLICKR(0XF16E), // + ADN(0XF170), // + BITBUCKET(0XF171), // + BITBUCKET_SQUARE(0XF172), // + TUMBLR(0XF173), // + TUMBLR_SQUARE(0XF174), // + LONG_ARROW_DOWN(0XF175), // + LONG_ARROW_UP(0XF176), // + LONG_ARROW_LEFT(0XF177), // + LONG_ARROW_RIGHT(0XF178), // + APPLE(0XF179), // + WINDOWS(0XF17A), // + ANDROID(0XF17B), // + LINUX(0XF17C), // + DRIBBBLE(0XF17D), // + SKYPE(0XF17E), // + FOURSQUARE(0XF180), // + TRELLO(0XF181), // + FEMALE(0XF182), // + MALE(0XF183), // + GITTIP(0XF184), // + SUN_O(0XF185), // + MOON_O(0XF186), // + ARCHIVE(0XF187), // + BUG(0XF188), // + VK(0XF189), // + WEIBO(0XF18A), // + RENREN(0XF18B), // + PAGELINES(0XF18C), // + STACK_EXCHANGE(0XF18D), // + ARROW_CIRCLE_O_RIGHT(0XF18E), // + ARROW_CIRCLE_O_LEFT(0XF190), // + CARET_SQUARE_O_LEFT(0XF191), // + DOT_CIRCLE_O(0XF192), // + WHEELCHAIR(0XF193), // + VIMEO_SQUARE(0XF194), // + TRY(0XF195), // + PLUS_SQUARE_O(0XF196); + + private static final String fontFamily = "FontAwesome"; + private int codepoint; + + FontAwesome(int codepoint) { + this.codepoint = codepoint; + } + + /** + * Unsupported: {@link FontIcon} does not have a MIME type and is not a + * {@link Resource} that can be used in a context where a MIME type would be + * needed. + */ + @Override + public String getMIMEType() { + throw new UnsupportedOperationException(FontIcon.class.getSimpleName() + + " should not be used where a MIME type is needed."); + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.FontIcon#getFontFamily() + */ + @Override + public String getFontFamily() { + return fontFamily; + } + + /* + * (non-Javadoc) + * + * @see com.vaadin.ui.FontIcon#getCodepoint() + */ + @Override + public int getCodepoint() { + return codepoint; + } + + @Override + public String getHtml() { + return "&#x" + Integer.toHexString(codepoint) + ";"; + } + +} diff --git a/server/src/com/vaadin/server/FontIcon.java b/server/src/com/vaadin/server/FontIcon.java new file mode 100644 index 0000000000..45279f2c44 --- /dev/null +++ b/server/src/com/vaadin/server/FontIcon.java @@ -0,0 +1,67 @@ +/* + * Copyright 2000-2014 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.server; + +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.ui.Label; + +/** + * A font icon is a type of icon that is made by displaying one character from a + * specially constructed font containing icons ("icon font"). + *

+ * {@link FontIcon} is a custom resource type which uses the URI scheme + * fonticon://<fontfamily>/<codepoint> to reference a + * specific icon from a specific icon font.
+ *

+ * + * @since 7.2 + * @author Vaadin Ltd + */ +public interface FontIcon extends Resource { + /** + * Returns the name (font family) of the font from which this icon comes. + * The name is used to apply the correct font where the icon is used. + * + * @since 7.2 + * @return + */ + public String getFontFamily(); + + /** + * Returns the unicode codepoint (character location) for this icon within + * the font given in {@link #getFontFamily()}. + *

+ * For example, 0x0021 would in a regular font be the codepoint for the + * exclamation-point character.
+ * When constructing icon fonts, it might be a good idea to use the + * codepoints in the "Private use area", from 0xE000 0xF8FF. + *

+ * + * @since 7.2 + * @return + */ + public int getCodepoint(); + + /** + * Returns HTML that can be used to display the icon in places where HTML + * can be used, such as a {@link Label} with {@link ContentMode#HTML}. + * + * + * @since 7.2 + * @return HTML needed to display icon + */ + public String getHtml(); +} diff --git a/server/src/com/vaadin/server/ResourceReference.java b/server/src/com/vaadin/server/ResourceReference.java index 6747dd2b74..4bc8febd72 100644 --- a/server/src/com/vaadin/server/ResourceReference.java +++ b/server/src/com/vaadin/server/ResourceReference.java @@ -67,6 +67,13 @@ public class ResourceReference extends URLReference { final String uri = "theme://" + ((ThemeResource) resource).getResourceId(); return uri; + } else if (resource instanceof FontIcon) { + // fonticon://[font-family]/[codepoint] + final FontIcon icon = (FontIcon) resource; + final String uri = ApplicationConstants.FONTICON_PROTOCOL_PREFIX + + urlEncode(icon.getFontFamily()) + "/" + + Integer.toHexString(icon.getCodepoint()); + return uri; } else { throw new RuntimeException(getClass().getSimpleName() + " does not support resources of type: " diff --git a/shared/src/com/vaadin/shared/ApplicationConstants.java b/shared/src/com/vaadin/shared/ApplicationConstants.java index a81f29b77c..d54823ee60 100644 --- a/shared/src/com/vaadin/shared/ApplicationConstants.java +++ b/shared/src/com/vaadin/shared/ApplicationConstants.java @@ -35,6 +35,7 @@ public class ApplicationConstants implements Serializable { public static final String APP_PROTOCOL_PREFIX = "app://"; public static final String VAADIN_PROTOCOL_PREFIX = "vaadin://"; + public static final String FONTICON_PROTOCOL_PREFIX = "fonticon://"; public static final String PUBLISHED_PROTOCOL_NAME = "published"; public static final String PUBLISHED_PROTOCOL_PREFIX = PUBLISHED_PROTOCOL_NAME + "://"; diff --git a/uitest/src/com/vaadin/tests/fonticon/FontIcons.java b/uitest/src/com/vaadin/tests/fonticon/FontIcons.java new file mode 100644 index 0000000000..5511acf3bf --- /dev/null +++ b/uitest/src/com/vaadin/tests/fonticon/FontIcons.java @@ -0,0 +1,226 @@ +/* + * 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.tests.fonticon; + +import com.vaadin.event.Action; +import com.vaadin.event.Action.Handler; +import com.vaadin.server.FontAwesome; +import com.vaadin.server.FontIcon; +import com.vaadin.server.Page; +import com.vaadin.server.Resource; +import com.vaadin.server.ThemeResource; +import com.vaadin.server.VaadinRequest; +import com.vaadin.shared.Position; +import com.vaadin.shared.ui.label.ContentMode; +import com.vaadin.tests.components.AbstractTestUI; +import com.vaadin.ui.AbstractSelect; +import com.vaadin.ui.Accordion; +import com.vaadin.ui.Button; +import com.vaadin.ui.Button.ClickEvent; +import com.vaadin.ui.CheckBox; +import com.vaadin.ui.ComboBox; +import com.vaadin.ui.Component; +import com.vaadin.ui.DateField; +import com.vaadin.ui.GridLayout; +import com.vaadin.ui.Label; +import com.vaadin.ui.Link; +import com.vaadin.ui.ListSelect; +import com.vaadin.ui.MenuBar; +import com.vaadin.ui.MenuBar.MenuItem; +import com.vaadin.ui.NativeButton; +import com.vaadin.ui.NativeSelect; +import com.vaadin.ui.Notification; +import com.vaadin.ui.OptionGroup; +import com.vaadin.ui.Panel; +import com.vaadin.ui.Slider; +import com.vaadin.ui.TabSheet; +import com.vaadin.ui.Table; +import com.vaadin.ui.Table.Align; +import com.vaadin.ui.Table.RowHeaderMode; +import com.vaadin.ui.TextArea; +import com.vaadin.ui.TextField; +import com.vaadin.ui.Tree; +import com.vaadin.ui.TwinColSelect; +import com.vaadin.ui.Upload; +import com.vaadin.ui.VerticalLayout; + +/** + * + * @since + * @author Vaadin Ltd + */ +public class FontIcons extends AbstractTestUI { + + @Override + protected void setup(VaadinRequest request) { + buildUI(FontAwesome.ANDROID); + } + + private void buildUI(final Resource icon) { + VerticalLayout layout = new VerticalLayout(); + setContent(layout); + layout.setMargin(true); + + layout.setIcon(icon); + + layout.addComponent(new Button("Switch icon type", + new Button.ClickListener() { + + @Override + public void buttonClick(ClickEvent event) { + buildUI(icon instanceof FontIcon ? new ThemeResource( + "../runo/icons/16/user.png") + : FontAwesome.ANDROID); + } + })); + + Handler actionHandler = new Handler() { + Action[] actions = { new Action("Do it!", icon) }; + + @Override + public void handleAction(Action action, Object sender, Object target) { + + } + + @Override + public Action[] getActions(Object target, Object sender) { + return actions; + } + }; + + // Notification + Notification n = new Notification("Hey there!"); + n.setIcon(icon); + n.setPosition(Position.BOTTOM_CENTER); + n.setDelayMsec(-1); + n.show(Page.getCurrent()); + + // grid of compoents + GridLayout gl = new GridLayout(4, 5); + gl.setSpacing(true); + layout.addComponent(gl); + + // Basic components, caption icon only + Class[] components = { Button.class, CheckBox.class, + DateField.class, NativeButton.class, Link.class, Label.class, + Panel.class, Slider.class, TextArea.class, TextField.class, + Upload.class }; + for (Class clazz : components) { + Component c; + try { + c = (Component) clazz.newInstance(); + } catch (Exception e) { + e.printStackTrace(); + continue; + } + c.setCaption(clazz.getSimpleName()); + c.setIcon(icon); + gl.addComponent(c); + } + + // TabSheet, caption + tab icons + TabSheet tabs = new TabSheet(); + tabs.setCaption("TabSheet"); + tabs.setIcon(icon); + tabs.addStyleName("myTabs"); + tabs.addTab(new Label("Content 1"), "Tab 1", icon); + tabs.addTab(new Label("Content 2"), "Tab 2", icon); + tabs.setWidth("150px"); + gl.addComponent(tabs); + + // Accordion, caption + tab icons + Accordion acc = new Accordion(); + acc.setCaption("Accordion"); + acc.setIcon(icon); + acc.addTab(new Label(), "Section 1", icon); + acc.addTab(new Label(), "Section 2", icon); + gl.addComponent(acc); + + // Table, caption + column + row + action icons + Table tbl = new Table("Table"); + tbl.setRowHeaderMode(RowHeaderMode.ICON_ONLY); + tbl.setIcon(icon); + tbl.addContainerProperty("Column 1", String.class, "Row", "Column 1", + icon, Align.LEFT); + tbl.addContainerProperty("Column 2", String.class, "Row", "Column 2", + icon, Align.LEFT); + tbl.setItemIcon(tbl.addItem(), icon); + tbl.setItemIcon(tbl.addItem(), icon); + tbl.setItemIcon(tbl.addItem(), icon); + tbl.setPageLength(3); + gl.addComponent(tbl); + tbl.addActionHandler(actionHandler); + + // Selects, caption + item icons + Class[] selects = { ComboBox.class, NativeSelect.class, + ListSelect.class, TwinColSelect.class, OptionGroup.class }; + for (Class clazz : selects) { + AbstractSelect sel; + try { + sel = (AbstractSelect) clazz.newInstance(); + } catch (Exception e) { + e.printStackTrace(); + continue; + } + sel.setCaption(clazz.getSimpleName()); + sel.setIcon(icon); + sel.addItem("One"); + sel.setItemIcon("One", icon); + sel.addItem("Two"); + sel.setItemIcon("Two", icon); + gl.addComponent(sel); + } + + // MenuBar, caption + item + sub-item icons + MenuBar menu = new MenuBar(); + menu.setIcon(icon); + menu.setCaption("MenuBar"); + MenuItem mi = menu.addItem("File", icon, null); + MenuItem smi = mi.addItem("Item", icon, null); + smi = mi.addItem("Item", icon, null); + smi = smi.addItem("Item", icon, null); + gl.addComponent(menu); + + // Tree, caption + item + subitem + action icons + Tree tree = new Tree("Tree"); + tree.addItem("Root"); + tree.setItemIcon("Root", icon); + tree.addItem("Leaf"); + tree.setItemIcon("Leaf", icon); + tree.setParent("Leaf", "Root"); + tree.expandItemsRecursively("Root"); + tree.addActionHandler(actionHandler); + gl.addComponent(tree); + + // All of FontAwesome + String allIcons = ""; + for (FontIcon ic : FontAwesome.values()) { + allIcons += ic.getHtml() + " "; + } + layout.addComponent(new Label(allIcons, ContentMode.HTML)); + } + + @Override + protected String getTestDescription() { + return "Font icons should show up in all the right places"; + } + + @Override + protected Integer getTicketNumber() { + return 13152; + } + +} diff --git a/uitest/src/com/vaadin/tests/fonticon/FontIconsTest.java b/uitest/src/com/vaadin/tests/fonticon/FontIconsTest.java new file mode 100644 index 0000000000..af54b73ae3 --- /dev/null +++ b/uitest/src/com/vaadin/tests/fonticon/FontIconsTest.java @@ -0,0 +1,36 @@ +/* + * 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.tests.fonticon; + +import java.io.IOException; + +import org.junit.Test; + +import com.vaadin.tests.tb3.MultiBrowserTest; + +/** + * + * @since + * @author Vaadin Ltd + */ +public class FontIconsTest extends MultiBrowserTest { + + @Test + public void checkScreenshot() throws IOException { + openTestURL(); + compareScreen("all"); + } +}