3.5.9.2. 使用其它字体库中的图标
为了增强主题扩展,可能需要创建图标并将其嵌入到字体中,以及使用一些外部图标库。
- 在 web 模块中,为新图标创建实现
com.vaadin.server.FontIcon
接口的enum
类:
import com.vaadin.server.FontIcon;
import com.vaadin.server.GenericFontIcon;
public enum IcoMoon implements FontIcon {
HEADPHONES(0XE900),
SPINNER(0XE905);
public static final String FONT_FAMILY = "IcoMoon";
private int codepoint;
IcoMoon(int codepoint) {
this.codepoint = codepoint;
}
@Override
public String getFontFamily() {
return FONT_FAMILY;
}
@Override
public int getCodepoint() {
return codepoint;
}
@Override
public String getHtml() {
return GenericFontIcon.getHtml(FONT_FAMILY, codepoint);
}
@Override
public String getMIMEType() {
throw new UnsupportedOperationException(FontIcon.class.getSimpleName()
+ " should not be used where a MIME type is needed.");
}
public static IcoMoon fromCodepoint(final int codepoint) {
for (IcoMoon f : values()) {
if (f.getCodepoint() == codepoint) {
return f;
}
}
throw new IllegalArgumentException("Codepoint " + codepoint
+ " not found in IcoMoon");
}
}
- 向主题扩展添加新样式。建议在主题扩展的主文件夹中创建一个特定的子文件夹
fonts
,例如modules/web/themes/halo/com.company.demo/fonts
。将样式和字体文件放在特有的子文件夹中,例如fonts/icomoon
。
字体文件由以下扩展名表示:
.eot
,.svg
,.ttf
,.woff
.
本例中使用了一个开源字体集 icomoon
,由 4 个联合使用的文件组成:icomoon.eot
、 icomoon.svg
、 icomoon.ttf
、icomoon.woff
。
- 创建一个包含
@font-face
样式和一个图标样式 CSS 类的文件。下面是icomoon.scss
文件的示例,其中IcoMoon
css 类名对应于FontIcon#getFontFamily
方法返回的值:
@mixin icomoon-style {
/* use !important to prevent issues with browser extensions that change fonts */
font-family: 'icomoon' !important;
speak: none;
font-style: normal;
font-weight: normal;
font-variant: normal;
text-transform: none;
line-height: 1;
/* Better Font Rendering =========== */
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
@font-face {
font-family: 'icomoon';
src:url('icomoon.eot?hwgbks');
src:url('icomoon.eot?hwgbks#iefix') format('embedded-opentype'),
url('icomoon.ttf?hwgbks') format('truetype'),
url('icomoon.woff?hwgbks') format('woff'),
url('icomoon.svg?hwgbks#icomoon') format('svg');
font-weight: normal;
font-style: normal;
}
.IcoMoon {
@include icomoon-style;
}
- 在
halo-ext.scss
文件或其它主题扩展文件中添加对上述包含字体样式的文件的引用。
@import "fonts/icomoon/icomoon";
- 然后创建新的图标集,这是一个实现
Icons.Icon
接口的枚举:
import com.haulmont.cuba.gui.icons.Icons;
public enum IcoMoonIcon implements Icons.Icon {
HEADPHONES("ico-moon:HEADPHONES"),
SPINNER("ico-moon:SPINNER");
protected String source;
IcoMoonIcon(String source) {
this.source = source;
}
@Override
public String source() {
return source;
}
}
- 创建新的
IconProvider
.
为了管理自定义图标集,CUBA 框架提供了由 IconProvider
和 IconResolver
组成的机制。
IconProvider
是一个标记接口,只存在于 web 模块中,可以通过图标路径提供资源(com.vaadin.server.Resource
)。
IconResolver
bean 获取实现 IconProvider
接口的所有 bean,并遍历它们以找到可以为图标提供资源的 bean。
要使用这种机制,应该创建 IconProvider
的实现:
import com.haulmont.cuba.web.gui.icons.IconProvider;
import com.vaadin.server.Resource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@Order(10)
@Component
public class IcoMoonIconProvider implements IconProvider {
private final Logger log = LoggerFactory.getLogger(IcoMoonIconProvider.class);
@Override
public Resource getIconResource(String iconPath) {
Resource resource = null;
iconPath = iconPath.split(":")[1];
try {
resource = ((Resource) IcoMoon.class
.getDeclaredField(iconPath)
.get(null));
} catch (IllegalAccessException | NoSuchFieldException e) {
log.warn("There is no icon with name {} in the FontAwesome icon set", iconPath);
}
return resource;
}
@Override
public boolean canProvide(String iconPath) {
return iconPath.startsWith("ico-moon:");
}
}
这里我们用 @Order annotation
注解显式地为这个 bean 指定顺序。
- 在应用程序属性文件中注册自定义图标集:
cuba.iconsConfig = +com.company.demo.gui.icons.IcoMoonIcon
现在,在界面 XML 描述中可以直接引用图标的类和 枚举
元素 :
<button caption="Headphones" icon="ico-moon:HEADPHONES"/>
或者在 Java 控制器中:
spinnerBtn.setIconFromSet("ico-moon:SPINNER");
这样新图标会添加到按钮上:
- 覆盖图标集的图标
图标集机制可以覆盖其它图标集中的图标。为此,应该创建并注册一个具有相同图标(枚举值)但不同图标路径(source
)的新图标集(枚举)。在下面的示例中,创建了一个新的图标枚举MyIcon
,用于覆盖CubaIcon
图标集中的标准图标。
-
默认图标集:public enum CubaIcon implements Icons.Icon {
OK("font-icon:CHECK"),
CANCEL("font-icon:BAN"),
…
}
-
新图标集:public enum MyIcon implements Icons.Icon {
OK("icons/my-custom-ok.png"),
…
}
-
在web-app.properties
中注册的新图标集:cuba.iconsConfig = +com.company.demo.gui.icons.MyIcon
现在,新的 OK 图标将代替标准图标而被使用:Icons icons = AppBeans.get(Icons.NAME);
button.setIcon(icons.getIcon(CubaIcon.OK))
如果需要忽略重新定义的图标,仍然可以通过使用标准图标的路径而不是选项名称来使用标准图标:<button caption="Created" icon="icons/create.png"/>
或者button.setIcon(CubaIcon.CREATE_ACTION.source());