/** * Copyright (c) 2014-2017 by the respective copyright holders. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html */ package org.eclipse.smarthome.ui.icon; import java.io.InputStream; import java.util.Set; import org.eclipse.smarthome.core.i18n.I18nProvider; import org.eclipse.smarthome.ui.icon.IconSet.Format; import org.osgi.framework.BundleContext; /** * This is an abstract base class for implementing icon providers that serve icons from file resources. * These files could be read from the file system, directly from the bundle itself or from somewhere else that can * provide an {@link InputStream}. * * The resources are expected to follow the naming convention "<category>[-<state>].<format>", e.g. "alarm.png" or * "alarm-on.svg". * Resource names must be all lower case. Whether an icon is provided or not is determined by the existence of a * resource without a state postfix. * If a specific resource for a state is available, it will be used. If not, the default icon without a state postfix is * used. If the state is a decimal number between 0 and 100, the implementation will look for a resource with the next * smaller state postfix available. Example: For category "DimmableLight" and state 84, it will check for the resources * dimmablelight-82.png, dimmablelight-81.png, dimmablelight-80.png and return the first one it can find. * * @author Kai Kreuzer * */ abstract public class AbstractResourceIconProvider implements IconProvider { /** * The OSGi bundle context */ protected BundleContext context; /** * An I18nProvider service */ protected I18nProvider i18nProvider; /** * When activating the service, we need to keep the bundle context. * * @param context the bundle context provided through OSGi DS. */ protected void activate(BundleContext context) { this.context = context; } protected void setI18nProvider(I18nProvider i18nProvider) { this.i18nProvider = i18nProvider; } protected void unsetI18nProvider(I18nProvider i18nProvider) { this.i18nProvider = null; } @Override public Set<IconSet> getIconSets() { return getIconSets(null); } @Override public Integer hasIcon(String category, String iconSetId, Format format) { return hasResource(iconSetId, category.toLowerCase() + "." + format.toString().toLowerCase()) ? getPriority() : null; } @Override public InputStream getIcon(String category, String iconSetId, String state, Format format) { String resourceWithState = category + ((state != null) ? "-" + state.toLowerCase() : "") + "." + format.toString().toLowerCase(); if (hasResource(iconSetId, resourceWithState)) { return getResource(iconSetId, resourceWithState); } else { // let's treat all percentage-based categories try { Double stateAsDouble = Double.valueOf(state); if (stateAsDouble >= 0 && stateAsDouble <= 100) { for (int i = stateAsDouble.intValue(); i >= 0; i--) { String resourceWithNumberState = category + "-" + i + "." + format.toString().toLowerCase(); if (hasResource(iconSetId, resourceWithNumberState)) { return getResource(iconSetId, resourceWithNumberState); } } } } catch (NumberFormatException e) { // does not seem to be a number, so ignore it } return getResource(iconSetId, category + "." + format.toString().toLowerCase()); } } /** * Provides the priority of this provider. A higher value will give this provider a precedence over others. * * @return the priority as a positive integer */ abstract protected Integer getPriority(); /** * Provides the content of a resource for a certain icon set as a stream or null, if the resource does not exist. * * @param iconSetId the id of the icon set for which the resource is requested * @param resourceName the name of the resource * @return the content as a stream or null, if the resource does not exist */ abstract protected InputStream getResource(String iconSetId, String resourceName); /** * Checks whether a certain resource exists for a given icon set. * * @param iconSetId the id of the icon set for which the resource is requested * @param resourceName the name of the resource * @return true, if the resource exists, false otherwise */ abstract protected boolean hasResource(String iconSetId, String resourceName); }