/* * Copyright (c) 2003, KNOPFLERFISH project * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following * conditions are met: * * - Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * - Redistributions in binary form must reproduce the above * copyright notice, this list of conditions and the following * disclaimer in the documentation and/or other materials * provided with the distribution. * * - Neither the name of the KNOPFLERFISH project nor the names of its * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ package org.knopflerfish.bundle.desktop.swing; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Component; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.InputEvent; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseListener; import java.net.URL; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; import javax.swing.AbstractButton; import javax.swing.ButtonGroup; import javax.swing.Icon; import javax.swing.ImageIcon; import javax.swing.JCheckBoxMenuItem; import javax.swing.JComponent; import javax.swing.JLabel; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JScrollPane; import javax.swing.SwingConstants; import javax.swing.SwingUtilities; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.BundleEvent; public class LargeIconsDisplayer extends DefaultSwingBundleDisplayer { public LargeIconsDisplayer(BundleContext bc) { super(bc, "Large Icons", "Large icon display of bundles", false); } public void bundleChanged(BundleEvent ev) { super.bundleChanged(ev); // System.out.println(getClass().getName() + ": #" + ev.getBundle().getBundleId()); for(Iterator it = components.iterator(); it.hasNext(); ) { JLargeIcons comp = (JLargeIcons)it.next(); switch(ev.getType()) { case BundleEvent.INSTALLED: comp.addBundle(ev.getBundle()); break; case BundleEvent.UNINSTALLED: comp.removeBundle(ev.getBundle()); break; default: comp.updateBundleComp(ev.getBundle()); break; } } repaintComponents(); } public JComponent newJComponent() { return new JLargeIcons(); } class JLargeIcons extends JPanel { Map bundleMap = new TreeMap(); GridLayout grid; ImageIcon bundleIcon; JPanel panel; JScrollPane scroll; MouseListener contextMenuListener = null; JPopupMenu contextPopupMenu; Color selColor = new Color(200, 200, 255); public JLargeIcons() { setLayout(new BorderLayout()); setBackground(Color.white); grid = new GridLayout(0, 4); panel = new JPanel(grid); panel.setBackground(getBackground()); contextPopupMenu = new JPopupMenu(); ButtonGroup group = new ButtonGroup(); JCheckBoxMenuItem item = new JCheckBoxMenuItem("Sort by name"); item.setState(iconComparator == nameComparator); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { iconComparator = nameComparator; rebuildPanel(); } }); contextPopupMenu.add(item); group.add(item); item = new JCheckBoxMenuItem("Sort by bundle ID"); item.setState(iconComparator == null); item.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent ev) { iconComparator = null; rebuildPanel(); } }); contextPopupMenu.add(item); group.add(item); contextMenuListener = new MouseAdapter() { public void mousePressed(MouseEvent e) { maybeShowPopup(e); } public void mouseReleased(MouseEvent e) { maybeShowPopup(e); } private void maybeShowPopup(MouseEvent e) { if(contextPopupMenu != null && (e.isPopupTrigger() || ((e.getModifiers() & InputEvent.BUTTON2_MASK) != 0))) { Component comp = e.getComponent(); contextPopupMenu.show(comp, e.getX(), e.getY()); } } }; panel.addMouseListener(contextMenuListener); // handle scroll panel resizing to be able to set grid size scroll = new JScrollPane(panel) { int oldW = -1; int oldH = -1; public void setBounds(int x, int y, int w, int h) { super.setBounds(x, y, w, h); // avoid looping when rebuilding panel if(w != oldW || h != oldH) { oldW = w; oldH = h; rebuildPanel(); } } }; add(scroll, BorderLayout.CENTER); } public void addBundle(final Bundle b) { final long bid = b.getBundleId(); if(null == getBundleComponent(b)) { JLabel c = new JLabel(Util.getBundleName(b), bundleIcon, SwingConstants.CENTER) { { addMouseListener(new MouseAdapter() { public void mousePressed(MouseEvent ev) { if((ev.getModifiers() & InputEvent.CTRL_MASK) != 0) { bundleSelModel .setSelected(bid, !bundleSelModel.isSelected(bid)); } else { bundleSelModel.clearSelection(); bundleSelModel.setSelected(bid, true); } setBackground(getBackground()); } }); addMouseListener(contextMenuListener); setBorder(null); setOpaque(true); setBackground(Color.yellow); } public Color getBackground() { try { boolean bSel = bundleSelModel != null ? bundleSelModel.isSelected(b.getBundleId()) : false; return bSel ? selColor : JLargeIcons.this.getBackground(); } catch (Exception e) { return Color.black; } } }; // System.out.println("created icon " + c.getText()); c.setToolTipText(Util.bundleInfo(b)); c.setVerticalTextPosition(AbstractButton.BOTTOM); c.setHorizontalTextPosition(AbstractButton.CENTER); c.setPreferredSize(new Dimension(96, 64)); c.setBorder(null); c.setFont(getFont()); synchronized(bundleMap) { bundleMap.put(new Long(b.getBundleId()), c); } updateBundleComp(b); rebuildPanel(); } } Comparator nameComparator = new Comparator() { public int compare(Object o1, Object o2) { Bundle b1 = Activator.getTargetBC().getBundle(((Long)o1).longValue()); Bundle b2 = Activator.getTargetBC().getBundle(((Long)o2).longValue()); if(b1 == b2) { return 0; } if(b1 == null) { return -1; } if(b2 == null) { return 1; } return Util.getBundleName(b1).compareToIgnoreCase(Util.getBundleName(b2)); } }; Comparator iconComparator = null; void rebuildPanel() { SwingUtilities.invokeLater(new Runnable() { public void run() { synchronized(bundleMap) { panel.removeAll(); // Comparator comp = nameComparator; Set set = new TreeSet(iconComparator); set.addAll(bundleMap.keySet()); int w = 0; int h = 0; for(Iterator it = set.iterator(); it.hasNext(); ) { Long bid = (Long)it.next(); JComponent c = (JComponent)bundleMap.get(bid); Dimension size = c.getPreferredSize(); w = Math.max(w, size.width); h = Math.max(h, size.height); } Dimension size = scroll.getViewport().getExtentSize(); if(size.width != 0) { grid.setColumns(size.width / w); grid.setRows(0); } for(Iterator it = set.iterator(); it.hasNext(); ) { Long bid = (Long)it.next(); Component c = (Component)bundleMap.get(bid); panel.add(c); } } revalidate(); repaint(); } }); } public void removeBundle(Bundle b) { synchronized(bundleMap) { bundleMap.remove(new Long(b.getBundleId())); icons.remove(b); } rebuildPanel(); } JComponent getBundleComponent(Bundle b) { synchronized(bundleMap) { return (JComponent)bundleMap.get(new Long(b.getBundleId())); } } // Bundle -> BundleImageIcon Map icons = new HashMap(); public void updateBundleComp(Bundle b) { JLabel c = (JLabel)getBundleComponent(b); if(c == null) { addBundle(b); return; } c.setToolTipText(Util.bundleInfo(b)); Icon icon = (Icon)icons.get(b); if(icon == null) { URL appURL = null; String iconName = (String)b.getHeaders().get("Application-Icon"); if(iconName == null) { iconName = ""; } iconName = iconName.trim(); if(iconName != null && !"".equals(iconName)) { try { appURL = b.getResource(iconName); } catch (Exception e) { Activator.log.error("Failed to load icon", e); } } // System.out.println("#" + b.getBundleId() + ", appURL=" + appURL); try { if(Util.hasMainClass(b)) { icon = new BundleImageIcon(b, appURL != null ? appURL : getClass().getResource("/jarexec.gif")); } else if(Util.hasActivator(b)) { icon = new BundleImageIcon(b, appURL != null ? appURL : getClass().getResource("/bundle.png")); } else { icon = new BundleImageIcon(b, appURL != null ? appURL : getClass().getResource("/lib.png")); } } catch (Exception e) { Activator.log.error("Failed to load icon, appURL=" + appURL); icon = new BundleImageIcon(b, getClass().getResource("/bundle.png")); } icons.put(b, icon); } c.setIcon(icon); c.invalidate(); c.repaint(); invalidate(); repaint(); } } }