/** * OrbisGIS is a java GIS application dedicated to research in GIScience. * OrbisGIS is developed by the GIS group of the DECIDE team of the * Lab-STICC CNRS laboratory, see <http://www.lab-sticc.fr/>. * * The GIS group of the DECIDE team is located at : * * Laboratoire Lab-STICC – CNRS UMR 6285 * Equipe DECIDE * UNIVERSITÉ DE BRETAGNE-SUD * Institut Universitaire de Technologie de Vannes * 8, Rue Montaigne - BP 561 56017 Vannes Cedex * * OrbisGIS is distributed under GPL 3 license. * * Copyright (C) 2007-2014 CNRS (IRSTV FR CNRS 2488) * Copyright (C) 2015-2017 CNRS (Lab-STICC UMR CNRS 6285) * * This file is part of OrbisGIS. * * OrbisGIS is free software: you can redistribute it and/or modify it under the * terms of the GNU General Public License as published by the Free Software * Foundation, either version 3 of the License, or (at your option) any later * version. * * OrbisGIS is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with * OrbisGIS. If not, see <http://www.gnu.org/licenses/>. * * For more information, please consult: <http://www.orbisgis.org/> * or contact directly: * info_at_ orbisgis.org */ package org.orbisgis.omanager.ui; import java.awt.Component; import java.awt.Dimension; import java.awt.Graphics; import java.awt.Image; import java.awt.image.BufferedImage; import java.beans.EventHandler; import java.beans.PropertyChangeListener; import java.net.URI; import java.net.URL; import java.util.ArrayList; import java.util.List; import javax.swing.ImageIcon; import javax.swing.JLabel; import javax.swing.JList; import javax.swing.ListCellRenderer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.osgi.framework.Bundle; /** * @author Nicolas Fortin */ public class BundleListRenderer implements ListCellRenderer<BundleItem> { private static final Logger LOGGER = LoggerFactory.getLogger(BundleListRenderer.class); private ListCellRenderer<? super BundleItem> lookAndFeelRenderer; private static Dimension bundleIconDimension = new Dimension(32,32); private static final ImageIcon defaultIcon = new ImageIcon(BundleListRenderer.class.getResource("defaultIcon.png")); private static final ImageIcon activeLayer = new ImageIcon(BundleListRenderer.class.getResource("active_layer.png")); private static final ImageIcon obrIcon = mergeIcons(defaultIcon.getImage(),new ImageIcon(BundleListRenderer.class.getResource("obr.png")).getImage()); private static final String ICON_SEPARATOR = ","; private static final String ICON_SIZE_PROP = "size="; private static final String ICON_HEADER = "Bundle-Icon"; public BundleListRenderer(JList list) { initialize(list); } private static ImageIcon mergeIcons(Image bottom,Image top) { BufferedImage image = new BufferedImage(bundleIconDimension.width, bundleIconDimension.height, BufferedImage.TYPE_INT_ARGB); Graphics g = image.getGraphics(); g.drawImage(bottom,0,0,null); g.drawImage(top, 0, 0, null); return new ImageIcon(image); } /** * * @param bundle * @param path Uri or Jar relative path. * @return */ private ImageIcon pathToImage(Bundle bundle, String path) { if(path.isEmpty()) { return null; } URI iconUri = URI.create(path); if(!iconUri.isAbsolute()) { // In the JAR URL entry = bundle.getEntry(path); if(entry != null) { return new ImageIcon(entry); } } else { //TODO Download ? } return null; } /** * Find the most appropriate Icon path using the Icon header * @param icons * @return */ public static String getBundleIconPath(String icons) { if(icons!=null) { List<String> iconList = new ArrayList<>(); if(icons.contains(ICON_SEPARATOR)) { for(String icon_descr : icons.split(ICON_SEPARATOR)) { iconList.add(icon_descr); } } else { iconList.add(icons); } String best_path = ""; int best_width = 0; for(String icon_descr : iconList) { // Take the best icon size int size_pos = icon_descr.indexOf(ICON_SIZE_PROP); int size_val = 0; String iconPath = new String(icon_descr); if(size_pos>1) { size_val = Integer.valueOf(icon_descr.substring(size_pos+ICON_SIZE_PROP.length() ,icon_descr.length()).trim()); iconPath = icon_descr.substring(0,size_pos-1).trim(); } if(best_width==0 || size_val == bundleIconDimension.width || (size_val > best_width && best_width != bundleIconDimension.width)) { best_path = iconPath; best_width = size_val; } } if(!best_path.isEmpty()) { return best_path; } } return ""; } private ImageIcon getBundleIcon(Bundle bundle) { return pathToImage(bundle,getBundleIconPath(bundle.getHeaders().get(ICON_HEADER))); } @Override public Component getListCellRendererComponent(JList<? extends BundleItem> jList, BundleItem bi, int i, boolean b, boolean b2) { Component lafComp = lookAndFeelRenderer.getListCellRendererComponent(jList,bi,i,b,b2); if(lafComp instanceof JLabel && bi!=null) { try { JLabel label = (JLabel)lafComp; ImageIcon bundleImage = defaultIcon; // Open the bundle icon if defined if(bi.getBundle()!=null) { Bundle bundle = bi.getBundle(); try { ImageIcon customBundleImage = getBundleIcon(bundle); if(customBundleImage!=null) { bundleImage = customBundleImage; } } catch (Exception ex) { // If bundle state is not ready or an error occur when loading // an icon then show the default icon. LOGGER.error(ex.getLocalizedMessage(),ex); } } if(bi.getBundle()!=null && bi.getBundle().getState()== Bundle.ACTIVE) { label.setIcon(mergeIcons(bundleImage.getImage(),activeLayer.getImage())); } else if(bi.getBundle()==null && bi.getObrResource()!=null) { label.setIcon(obrIcon); } else { label.setIcon(bundleImage); } StringBuilder sb = new StringBuilder(); sb.append("<html><h4>"); sb.append(bi.getPresentationName()); sb.append(" ("); sb.append(bi.getVersion()); sb.append(")</h4>"); sb.append(bi.getShortDescription()); sb.append("</html>"); label.setText(sb.toString()); } catch(Exception ex) { LOGGER.error(ex.getLocalizedMessage(),ex); } } return lafComp; } /** * Update the native renderer. * Warning, Used only by PropertyChangeListener on UI property */ public void updateLFRenderer() { lookAndFeelRenderer = new JList<BundleItem>().getCellRenderer(); } private void initialize(JList list) { updateLFRenderer(); list.addPropertyChangeListener("UI", EventHandler.create(PropertyChangeListener.class, this, "updateLFRenderer")); } }